Function.prototype.bind()
Title | content |
---|---|
Bind definition | What is a Bind function? |
bind use | How to use the Bind function? |
BIND’s implementation principle | How to implement the Bind function? |
bind example | bind function to implement inheritance, etc. |
bind()
Method to create aNew function, inWhen
bind()
is called, this new functionthis
Deded up asbind()
The first parameter, andThe rest of the parameters will be used as a parameter of the new function, use during the call.
const jackdan = {
age: 27,
height: 185,
getAge: function() {
return this.age;
},
getHeight: function() {
return this.height;
}
}
const age = jackdan.getAge;
console.log(age()); // The function gets invoked at the global scope
// undefined
const age1 = jackdan.getAge();
console.log(age1);
// 27
const jackdanAge = age.bind(jackdan);
console.log(jackdanAge());
// 27
function.bind(thisArg[, arg1[, arg2[, ...]]]);
-
callBinding function
this
parameter passed totarget functionThe value of. If used
new
The component constructing the binding function, then ignore the value (why?). Usebind
When creating a function insetTimeout
thisArg
Any original value transmitted toobject
. ifThe parameter list of the
bind
function is empty, orthisArg
Yesnull
orundefined
, executing scopethis
will be regarded as a new functionthisArg
。 -
Why is it
new
The computing symbol constructor is ignored when the binding function of the binding functionthisArg
? This is actually based onnew
The characteristics of the operator itself are related,new
The characteristics of the operator are as follows:
1. Create an empty simple JavaScript object({
});
2.as a step1New object adding attributes`__proto__`, link the property to the prototype object of the constructive function;3.will step by step1New Objects`this`context;4.If the function does not return the object, return`this`。
- Bind Role: Create a new function (we can actually call it -create a copy called the function), but it will
The value of
this
is set toThe first parameter passed to itis alsothisArgs
。 - NEW’s role: will
The value of
this
is set toNew air object。 - Therefore, if used
new
Try to call andthis
The function of the value binding of the keyword, thennew
Keywords will coverbind
this
Set as empty object。
function A() {
// console.log(this);
console.log('test');
}
var a = new A();
// Output test
- native implementation:
function A() {
console.log('test');
}
function New(fn) {
var obj = {
};
obj.__proto__ = fn.prototype;
fn.apply(obj, arguments);
return obj;
}
var a = New(A);
// Output test
new
Detailed introduction Reference。
- target functionWhen the call is called, it is presetbinding function
The parameters in the parameter list of
.
- Return onecopy of the original function, and own specified
this
value and valueinitial parameters。
-
bind()
function will create oneNew binding function(bound function
,BF
). The binding function is aexotic function object
(weird function object), it packaged the original function object. transferBinding functionusually causes executionPackaging function。 -
Binding functionhas the following internal attributes:
1. [[BoundTargetFunction]] -Packaging function object2. [[BoundThis]] -When calling the packaging function, always use it`this`Value Value.
The3. [[BoundArguments]] -list, any call to the packaging function will give priority to filling the parameter list with the list element.4. [[Call]] -execute code associated with this object. Call the expression by function call. The parameters of the internal method are a
The`this`value and a list containing the parameters passed to the function by calling the expression.
- When the call binding function is called, it calls
Internal method on[[BoundTargetFunction]][[Call]], like thisCall(boundThis, args). in,boundThisYes[[BoundThis]],argsis ** [[Boundarguments]] ** plus the parameter list passed through the function call.
- binding function can also be used
new
The computing symbol structure, it will be manifested astarget function has been built like. which providedthis
Value will be ignored, butPre -parameter will still be provided to the analog function。
// I hope I can run this instance carefully, which is worth studying and repeated verification
function myFunc() {
console.log('this=', this.name,
'constructor=', this.constructor.name,
this.constructor === myFunc)
}
myFunc.prototype.name = "PROTOTYPE";
let myObj = {
name: 'jackdan'};
myFunc();
// let myFunc1 = new myFunc();
// var bound = myFunc.bind({name: 'jackdan'});
myObj.f = myFunc;
myObj.f();
var func = new myFunc();
var bound1 = myFunc.bind({
name: 'jackdan'});
bind()
The easiest usage isCreate a function, no matter how to call,This function has the samethis
value。- javascript novice for novice often made a mistake isPut a method out of the object,and then call, expected method
this
is the original object (such as inThis method is introduced in the callback)。 - If you do not do special treatment, you will usually lose the original object. Based on this function, the original object creates a binding function to cleverly solve this problem:
// In non -strict mode
this.age = 30;
var obj = {
age: 27,
getAge: function() {
return this.x;
}
}
obj.getX(); // 27
var totalX = obj.getX;
totalX(); // Return 30 -because the function is called in the global scope
// Create a new function that binds 'this' to OBJ object
// Novices may confuse the attributes of global variables with OBJ
Another simplest usage of
var boundX = totalX.bind(obj);
boundX(); // 27
bind()
is to make a function have the initial parameters of the preset. As long as these parameters (if.)bind()
The parameters are written inthis
later. When the binding function is called, these parameters are inserted into the starting position of the parameter list of the target function, and the parameters passing to the binding function will follow them.
function toArray() {
return Array.prototype.slice.call(arguments);
}
function addArguments(arg1, arg2) {
return arg1 + arg2;
}
var argList = toArray(1, 2, 3); // [1, 2, 3]
var result1 = addArguments(1, 2); // 3
// Create a function that has a preset parameter list.
// Create a function that has a preset parameter list.
var leadingThirtysevenList = toArray.bind(null, 37);
// Create a function that has the preset first parameter
var addThirtySeven = addArguments.bind(null, 37);
var list2 = leadingThirtysevenList();
// [37]
var list3 = leadingThirtysevenList(1, 2, 3);
// [37, 1, 2, 3]
var result2 = addThirtySeven(5);
// 37 + 5 = 42
var result3 = addThirtySeven(5, 10);
// 37 + 5 = 42, the second parameter is ignored
- By default, use
window.setTimeout()
time,this
Keywords will point towindow
(or global) object. Need to be in the class methodthis
When pointing to a class instance, you may need to explicitly putthis
Binded to the callback function, you will not lose the reference to the instance.
function LateBloomer() {
this.petalCount = Math.ceil(Math.random() * 12) + 1;
}
// State Bloom after 1 second
LateBloomer.prototype.bloom = function() {
window.setTimeout(this.declare.bind(this), 1000);
};
LateBloomer.prototype.declare = function() {
console.log('I am a beautiful flower with ' +
this.petalCount + ' petals!');
};
var flower = new LateBloomer();
flower.bloom(); // One second after one second, call the 'decay' method
- Binding function automatically adapts toUse
new
The operator to construct a new example created by the target function. When a binding function is used forBuild a value, originally providedthis
will be ignored. butThe parameter list provided will still be inserted before the parameter list when the constructor calls(also verified before).
Remarks: This part demonstrates the ability of JavaScript and records Bind () advance usage. The following method is not the best solution, and it may not be used in any production environment.
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function() {
return this.x + ',' + this.y;
};
var p = new Point(1, 2);
p.toString(); // '1,2'
var emptyObj = {
};
var YAxisPoint = Point.bind(emptyObj, 0/*x*/);
// Polyfill below does not support running this line code,
// But using the native Bind method to run is no problem:
var YAxisPoint = Point.bind(null, 0/*x*/);
/*(Inf note: Polyfill's bind method, if the first parameter of Bind is added,
That is, the newly binding This of Object (this), the packaging as the object,
Because Object (NULL) is {}, it can also be supported)*/
var axisPoint = new YAxisPoint(5);
axisPoint.toString(); // '0,5'
axisPoint instanceof Point; // true
axisPoint instanceof YAxisPoint; // true
new YAxisPoint(17, 42) instanceof Point; // true
- Please note that if you don’t need to do special treatmentCreate a harmony
new
The binding function used together. In other words, you don’t needDo a special processing to create a binding function that can be directly called, even if you want to bind the function morenew
Operations to call.
function Point(x, y) {
this.x = x;
this.y = y;
}
Point.prototype.toString = function() {
return this.x + ',' + this.y;
};
var p = new Point(1, 2);
p.toString(); // '1,2'
var emptyObj = {
};
var YAxisPoint = Point.bind(emptyObj, 0/*x*/);
// Polyfill below does not support running this line code,
// But using the native Bind method to run is no problem:
var YAxisPoint = Point.bind(null, 0/*x*/);
/*(Inf note: Polyfill's bind method, if the first parameter of Bind is added,
That is, the newly binding This of Object (this), the packaging as the object,
Because Object (NULL) is {}, it can also be supported)*/
var axisPoint = new YAxisPoint(5);
axisPoint.toString(); // '0,5'
axisPoint instanceof Point; // true
axisPoint instanceof YAxisPoint; // true
new YAxisPoint(17, 42) instanceof Point; // true
// can still be called as a normal function
// (even if this is usually not expected)
YAxisPoint(13);
emptyObj.x + ',' + emptyObj.y; // '0, 13'
- If you want a binding function to eithercan only be used with NEW operator, either you can only call directly, then you must be inTarget function is explicitly specified on this limit。
- When you want to need a specific
When the function of
this
value creates a shortcut (Shortcut),bind()
is also very easy to use. - You can use
Array.prototype.slice
to convert an array-like object (Array-Like Object) into a real array, take it as an example. You can simply write this:
var slice = Array.prototype.slice;
// ...
slice.apply(arguments);
bind()
can make this process simpler. In the following code,slice
YesFunction.prototype.apply()
Method binding function, and willArray.prototype
slice()
Method as a method as a waythis
value. This means that we don’t need the above one at allapply()
Call.
// The same effect as the "slice" effect of the previous code
var unboundSlice = Array.prototype.slice;
var slice = Function.prototype.apply.bind(unboundSlice);
// ...
slice(arguments);
Function.prototype.myBind = function() {
var self = this;
var thatArgs = arguments[0];
var args = Array.prototype.slice.call(arguments, 1);
if(typeof self !== 'function') {
// closest thing possible to the ECMAScript 5
// internal IsCallable function
throw new TypeError('Function.prototype.bind - ' +
'what is trying to be bound is not callable')
}
return function() {
var funcArgs = args.concat(Array.prototype.slice.call(arguments));
return self.apply(thatArgs, funcArgs);
}
}
- You can insert this code into your script, so that you
bind()
can also be partially used in an environment without built -in supportbind
。
Function.prototype.myBind = function(context) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fTemp = function() {
};
var fBound = function() {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fTemp ? this : context, args.concat(bindArgs));
}
fTemp.prototype = this.prototype;
fBound.prototype = new fTemp();
return fBound;
}
var jackdan = {
age: 27,
height: 185,
getAge: function() {
return this.age;
},
getHeight: function() {
return this.height;
}
}
var height = jackdan.getHeight;
var jackdanHeight = height.bind(jackdan);
console.log(jackdanHeight());
// 185
var obj = {
firstname: 'Dan',
lastname: 'Jack',
age: 27,
height: 185,
getName: function() {
var fullname = this.firstname + ' ' + this.lastname;
return fullname;
}
};
var myName = function() {
console.log(this.getName() + 'I choose you!')
}
var print = myName.bind(obj); // creates new object and binds obj. 'this' of obj === obj now
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind