当前位置:网站首页>This and object prototypes
This and object prototypes
2022-06-10 15:42:00 【CaraYQ】
About this
One 、this It's bound at run time , It's not binding at write time , Its context depends on the various conditions when the function is called .this The binding of has nothing to do with the location of the function declaration , It just depends on how the function is called .
Two 、 When a function is called , An activity record will be created ( Sometimes called execution context ). This record will contain where the function was called ( The call stack )、 How to call function 、 Input parameters and other information .this It's a property of this record , It will be used in the process of function execution .
this Comprehensive analysis
The position
One 、 The call location is where the function is called in the code ( Not the location of the statement ).
Two 、 The call location is in the previous call of the currently executing function
3、 ... and 、 You can think of the call stack as a chain of function calls
Binding rules
How the call position is determined during the execution of a function this Binding object of ? You must find the calling location , Then decide which of the following four rules to apply .
The default binding —— Independent function call
One 、 Consider the following code , The function calls with this The default binding for , therefore this Point to global object . So how do we know that the default binding is applied here ? Can be analyzed by The position Let's see foo() How is it called . In the code ,foo() It is called directly with a function reference without any modification , So you can only use the default binding , Cannot apply other rules . If strict mode is used (strict mode), The global object cannot be used for the default binding , therefore this Will be bound to undefined
function foo(){
console.log(this.a);
}
var a = 2;
foo();// 2
Two 、 although this The binding rules of depend entirely on the call location , But only foo() When running in non strict mode , The default binding can be bound to global objects ; Call... In strict mode foo() The default binding is not affected
function foo(){
console.log(this.a);
}
var a = 2;
(function() {
"use strict";
foo();// 2
})();
in other words , If the place called is a strict pattern , Does not affect the default binding , If a strict pattern is defined, it will affect
Implicit binding
One 、 Another rule to consider is whether there is a context object at the call location , Or whether it is owned or contained by an object
Two 、 Consider the following code :
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
obj.foo();// 2
The first thing to notice is that foo() Mode of declaration , And then how to add it as a reference property to obj Medium . But whether it's directly in obj Is it defined first and then added as a reference property , This function doesn't strictly belong to obj object . However , Call location will use obj Context to reference function , So you can say that when a function is called obj object “ Have ” perhaps “ contain ” it . When foo() When called , It is indeed preceded by the right obj References to . When a function references a context object , Implicit binding rules will this Bind to this context object . Because of the call foo() when this Bound to obj, therefore this.a and obj.a It's the same .
3、 ... and 、 In the object attribute reference chain, only the upper layer or the last layer plays a role in the calling position , namely this Just think about distance foo() Recent objects obj3
function foo() {
console.log(this.a);
}
var obj2 = {
a: 42,
foo: foo
};
var obj1 = {
a: 2,
obj2: obj2
};
obj1.obj2.foo();// 42
Implicit loss
One 、 One of the most common this The binding problem is that implicitly bound functions will lose bound objects , That is, it will apply the default binding , So that this Bind to a global object or undefined On , It depends on whether it's a strict model .
function foo() {
console.log(this.a);
}
var obj = {
a: 2,
foo: foo
};
var bar = obj.foo;// Function alias
var a = "opps, gobal";// a Properties of the global object
bar();// "opps, gobal"
explain :
- although
baryesobj.fooA reference to , But actually , It quotesfooThe function itself , So at this timebar()It's actually a function call without any decoration , So the default binding is applied . - This example also shows that the function does not belong to an object , Only when the function is called , An object refers to him .
var bar = obj.foo;What is passed is the function itself , and this It is determined by the calling host and environment , Function execution timebar();Time of executionthisPoint towindow
Two 、 Whether you pass a function into a language built-in function or a self declared function , Parameter passing is actually an implicit assignment , Therefore, when we pass in a function, it will also be implicitly assigned .
function foo() {
console.log(this.a);
}
function doFoo(fn) {
// fn In fact, the quotation is foo
fn();// Execution location
}
var obj = {
a: 2,
foo: foo
};
var a = "opps, gobal";// a Properties of the global object
doFoo(obj.foo);// "opps, gobal"
3、 ... and 、 see this Just want to , No concern this Who belongs to , Where are from , Only care about who the caller is when he calls .
Four 、 The function that calls the callback function may modify this. In some popular JavaScript The event handler in the library often takes the this Force binding to the DOM Element .
According to the binding
One 、 We must include an attribute that points to a function inside an object , And indirectly reference the function through this attribute , So that this indirect ( Implicit ) Bind to this object . So if we don't want to include function references inside objects , You want to force a function call on an object , We can use the... Of the function call(..) and apply(..) Method
Two 、 The first parameter of these two methods is an object , It's for this To prepare the , The function is then bound to the this. Because you can specify this Binding object of , So we call it explicit binding . If you pass in a raw value ( String type 、 Boolean type or numeric type ) To be this Binding object of , This primitive value will be converted to its object form ( That is to say new String(..)、newBoolean(..) perhaps new Number(..)). This is often referred to as “ Packing ”.
Hard binding
One 、 A variant of explicit binding can solve the problem of missing binding we proposed earlier .
function foo() {
console.log(this.a);
}
var obj = {
a: 2
};
var bar = function() {
foo.call(obj);
};
bar();// 2
setTimeout(bar, 100);// 2
// Hard bound bar It is impossible to modify his this
bar.call(window);// 2
We created the function bar(), And manually called inside it foo.call(obj), So force foo Of this Bound to obj. No matter how the function is called later bar, It's always manual obj On the call foo. This binding is an explicit mandatory binding , So we call it hard binding .
Two 、 The typical application scenario of hard binding is to create a wrapper function , It is responsible for receiving parameters and returning values
function foo(something) {
console.log(this.a,something);
return this.a + something;
}
var obj = {
a: 2
};
var bar = function() {
return foo.apply(obj, arguments);
};
var b = bar(3);// 2,3
console.log(b);// 5
3、 ... and 、 Another way to use it is to create an auxiliary function that can be reused :
function foo(something) {
console.log(this.a,something);
return this.a + something;
}
function bind(fn, obj){
return funciton() {
return fn.apply(obj, arguments);
}
}
var obj = {
a: 2
};
var bar = bind(foo, obj);
var b = bar(3);// 2,3
console.log(b);// 5
Four 、 Because hard binding is a very common pattern , therefore ES5 Provides built-in methods Function.prototype.bind.bind(..) It will return a new hard coded function , It will set the parameters you specify to this And call the original function .
5、 ... and 、Function.prototype.bind(..) A new wrapper function will be created , This function ignores its current this binding ( No matter what the bound object is ), And bind the objects we provide to this On .
API Called “ Context ”
JavaScript Many new built-in functions in the language and host environment , Both provide an optional parameter , Usually called “ Context ”(context), Its function and bind(..) equally , Make sure your callback function uses the specified this.
new binding
One 、“ Constructors ” Are some special methods in the class , Use new The constructor in the class is called when the class is initialized .
Two 、 stay JavaScript in , Constructors are just a few uses new The function called when the operator . They don't belong to a class , It doesn't instantiate a class . actually , They can't even be said to be a special function type , They are just new Operators call ordinary functions .
3、 ... and 、 All functions, including built-in object functions, can use new To call , Such function calls are called constructor calls . There is no such thing as “ Constructors ”, Only for functions “ To construct call ”.
Four 、 Use new To call a function , Or when a constructor call occurs , The following operations will be performed automatically :
- establish ( Or construction ) A new object
- This new object will be executed
[[Prototype]]Connect - This new object will be bound to the function call
this - If the function does not return another object , that
newThe function call in the expression will automatically return the new object .
priority
One 、 The priority of the default binding is the lowest of the four rules
Two 、 Test whether implicit binding or explicit binding has higher priority :
function foo() {
console.log(this.a);
}
var obj1 = {
a: 2,
foo: foo
};
var obj2 = {
a: 3,
foo: foo
};
obj1.foo();// 2
obj2.foo();// 3
obj1.foo.call(obj2);// 3
obj2.foo.call(obj1);// 2
Explicit binding takes precedence
3、 ... and 、 test new Which is the priority of binding or implicit binding :
function foo(something) {
this.a = something;
}
var obj1 = {
foo: foo
};
var obj2 = {
};
obj1.foo(2);
console.log(obj1.a);// 2
obj1.foo.call(obj2, 3);
console.log(obj2.a);// 3
var bar = new obj1.foo(4);// perform new When ,this It should point to the newly created instance object
console.log(obj1.a);// 2
console.log(bar.a);// 4, The instance object has a, And the value is 4, explain this It does point to the newly created instance object ,new Changed implicit binding ,new Binding takes precedence over implicit binding .
new Binding takes precedence over implicit binding .
Four 、 test new Who has the highest priority between binding and explicit binding
function foo(something){
this.a = something;
}
var obj1 = {
};
var bar = foo.bind(obj1);// obj1.foo
bar(2)
console.log(obj1.a);// 2
var baz = new bar(3)
console.log(obj1.a);// 2
console.log(baz.a);// 3
new Binding takes precedence over explicit binding :bar Be hard bound to obj1 On , however new bar(3) Not as we expected obj1.a It is amended as follows 3. contrary ,new Modified hard binding ( To obj1 Of ) call bar(..) Medium this. Because of the use of new binding , We got a name called baz The new object , also baz.a The value of is 3.
5、 ... and 、 The reason why new Hard bound functions are used in , The main purpose is to preset some parameters of the function , It's working new When initializing, you can only pass in the remaining parameters .bind(..) One of the functions of the is that you can remove the first parameter ( The first parameter is used for binding this) All other parameters are passed to the lower level function ( This technology is called “ Part of the application ”, yes “ currying ” A kind of ).
function foo() {
this.val = p1 + p2;
}
var bar = foo.bind(null, "p1");
var baz = new bar("p2");
baz.val;// p1p2

MDN:bind() Another simple use of is to make a function have a preset initial function . Just put these parameters ( If any ) As bind() The parameters of are written in this Back . When the binding function is called , These parameters are inserted at the beginning of the parameter list of the objective function , The parameters passed to the binding function will follow them .
Judge this
Determine which rule is applied to a function at a certain call position according to its priority :
- Is the function in new Call in (new binding )? If so this Binding is the newly created object .
var bar = new foo();
- Whether the function passes through call、apply( Explicitly bound ) Or hardbound calls ? If so ,this Binds the specified object .
var bar = foo.call(obj2);
- Function is called in a context object ( Implicit binding )? If so ,this That's the context object that's bound to .
var bar = obj1.foo();
- If not , Use default binding . If I'm in strict mode , It is bound to the undefined, Otherwise, bind to the global object .
var bar = foo();
Binding exception
Ignored this
One 、 If you put null perhaps undefined As this The binding object passed in call、apply perhaps bind, These values are ignored when called , The actual application is the default binding rules
Two 、 So under what circumstances will you introduce null Well ?
- Use
apply(..)Come on “ an ” An array , And pass in a function as an argument . bind(..)The parameters can be coriolised ( Preset some parameters )
function foo(a, b) {
console.log("a:"+a+",b:"+b);
}
// Expand the array into parameters
foo.apply(null,[2,3]);// a:2,b:3
// Use bind(...) Do the currification
var bar = foo.bind(null,2);
bar(3);// a:2,b:3
Both methods need to pass in a parameter as this Binding object of . If the function doesn't care this Words , You still need to pass in a placeholder , At this time null It might be a good choice
3、 ... and 、 stay ES6 in , It can be used ... Operator instead of apply(..) Come on “ an ” Array ,foo(...[1,2]) and foo(1,2) It's the same . It is a pity that there is no corrilized grammar at present , So you still need to use bind(..)
Four 、 hold null perhaps undefined As this The binding object passed in call、apply perhaps bind It may lead to many problems that are difficult to analyze and track bug, Not recommended .
Safer this
One 、 If we're ignoring this When binding, a special object is always passed in ( It's actually an empty object ), hold this Bind to this object , So anything about this The use of will be limited to this empty object , It has no effect on global objects .
Two 、 stay JavaScript The easiest way to create an empty object in is Object.create(null).Object.create(null) and {} It's like , But it doesn't create Object. prototype This Commission , So it's better than {}“ More empty ”
function foo(a, b) {
console.log("a:"+a+",b:"+b);
}
var x = Object.create(null);
// Expand the array into parameters
foo.apply(x,[2,3]);// a:2,b:3
// Use bind(...) Do the currification
var bar = foo.bind(x,2);
bar(3);// a:2,b:3
Indirect reference
One 、 It's possible that you ( Intentionally or unintentionally ) Create a function of “ Indirect reference ”, under these circumstances , Calling this function applies the default binding rules . Indirect references are most likely to occur during assignment :
function foo() {
console.log(this.a);
}
var a = 2;
var o = {
a: 3, foo: foo};
var p = {
a: 4};
o.foo();//3
(p.foo = o.foo)();// 2
explain :p.foo = o.foo It's a reference address ,(p.foo = o.foo)(); Equate to foo(), So the default binding is applied .
Two 、 The default binding depends on the calling place , The default binding this when undefined still window, It depends on where the function is defined , If the body of the function is in strict mode ,this Will be bound to undefined, otherwise this Will be bound to global objects .
Soft binding
One 、 After using hard binding, you cannot use implicit binding or explicit binding to modify this. If you can specify a global object and... For the default binding undefined Value beyond , Then you can achieve the same effect as hard binding , Keep the implicit binding or explicit binding modification at the same time this The ability of . We can achieve the desired effect through a method called soft binding :
if(!Function.prototype.softBind){
Function.prototype.softBind = function(obj){
var fn = this;
// Capture all curried Parameters
var curride = [].slice.call(arguments,1);
var bound = function(){
return fn.apply(
(!this || this === (window || global)) ? obj : this,curried.concat.apply(curried,arguments)
);
};
bound.prototype = Object.create(fn.prototype);
return bound;
};
}
In addition to soft binding ,softBind(..) Other principles and ES5 Built in bind(..) similar . It encapsulates the specified function , First, check the... At the time of the call this, If this Bind to a global object or undefined, Then set the specified default object obj Bound to the this, Otherwise, it will not be modified this. Besides , This code also supports the optional coritization
this morphology
One 、 Arrow function does not use this Four standard rules of , It's based on the outer layer ( Function or global ) Scope to determine this.
Two 、 Although the arrow function does not prototype, however instanceof Function by true
3、 ... and 、 Arrow functions are dynamically compiled at execution time , And inject code to capture this, And implement hard binding
边栏推荐
- Several reasons and solutions of virtual machine Ping failure
- What are the top ten futures companies with low handling fees? Is it safe?
- 姿态估计之2D人体姿态估计 - (OpenPose) Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields
- Wechat applet color gradient
- Summary of 5 years' experience in ERP odoo privilege management system setup
- 视觉SLAM常见的QR分解SVD分解等矩阵分解方式求解满秩和亏秩最小二乘问题(最全的方法分析总结)
- ORB_ Slam2 visual inertial tight coupling positioning technology route and code explanation 3 - tight coupling optimization model
- Cap version 6.1 Release Notice
- 探索数据可视化开发平台FlyFish开源背后的秘密!
- Tensorflow actual combat Google deep learning framework second edition learning summary tensorflow introduction
猜你喜欢

Yuntu says that every successful business system cannot be separated from apig

【高代码文件格式API】上海道宁为您提供文件格式API集——Aspose,只需几行代码即可创建转换和操作100多种文件格式

凸函数的Hessian矩阵与高斯牛顿下降法增量矩阵半正定性的理解

Hutool Usage Summary (VIP collection version)

如何構建以客戶為中心的產品藍圖:來自首席技術官的建議

VINS理論與代碼詳解4——初始化

Hessian matrix of convex function and Gauss Newton descent method

【MySQL基础】

uniapp中常用到的方法(部分) - 時間戳問題及富文本解析圖片問題

作用域和闭包
随机推荐
ORB_SLAM2视觉惯性紧耦合定位技术路线与代码详解0——整体框架与理论基础知识
QT 基于QScrollArea的界面嵌套移动
【MySQL基础】
Jaeger introduces native support for opentelemetry
C# 游戏雏形 人物地图双重移动
ORB_ Slam2 visual inertial tight coupling positioning technology route and code explanation 1 - IMU flow pattern pre integration
【无标题】
姿态估计之2D人体姿态估计 - (OpenPose) Realtime Multi-Person 2D Pose Estimation using Part Affinity Fields
这几个垂直类小众导航网站,你绝对不会想错过
苹果式中文:似乎表达清楚意思了,懂了没完全懂的苹果式宣传文案
How to improve document management
Explore the secrets behind the open source data visualization development platform flyfish!
The power of insight
Software intelligence: formal rules of AAAS system metrics and grammars
排序与分页
22. Generate Parentheses
Cmake actual combat record (I)
MySQL8安装详细步骤
Even some people say that ArrayList is twice as large. Today, I will take you to tear up the ArrayList source code
Technology sharing | quick intercom, global intercom