-
Notifications
You must be signed in to change notification settings - Fork 0
bind
jerryzhang edited this page Jan 31, 2023
·
1 revision
title: bind url: https://www.yuque.com/endday/blog/pumr4h
作者:若川 链接:https://juejin.im/post/5bec4183f265da616b1044d7 来源:掘金 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
var obj = {};
console.log(obj);
// bind本身是个方法,返回值也是一个方法
console.log(typeof Function.prototype.bind); // function
console.log(typeof Function.prototype.bind()); // function
// bind方法的name为bind,返回的方法的name为bound
console.log(Function.prototype.bind.name); // bind
console.log(Function.prototype.bind().name); // bound
- bind本身是个方法,返回值也是一个方法
- bind方法的name为bind,返回的方法的name为bound
var obj = {
name: 'baby',
};
function original(a, b){
console.log(this.name);
console.log([a, b]);
return false;
}
// 在使用bind方法传入的除第一个参数以外的参数
// 和执行bound函数传入的参数会拼接起来
var bound = original.bind(obj, 1);
// 在bind时传入了一个参数1,实际bound函数执行传入2
// 拼接出的实参其实是(1,2)
var boundResult = bound(2); // 'baby', [1, 2]
var bound = original.bind(obj);
// 这里bound执行时的实参就是(2)
var boundResult = bound(2); // 'baby', [2, undefined]
console.log(boundResult); // false
console.log(original.bind.name); // 'bind'
console.log(original.bind.length); // 1 bind的形参个数为1,就是this指向
console.log(original.bind().length); // 2 返回original函数的形参个数
// bind()返回函数的name为bound + 空格 + 调用bind的函数名
console.log(bound.name); // 'bound original'
console.log((function(){}).bind().name); // 'bound '
console.log((function(){}).bind().length); // 0
- 在使用bind方法传入的除第一个参数以外的参数,和执行bound函数传入的参数会拼接起来
- bind返回的函数的形参个数和原函数保持一致
Function.prototype.bindFn = function bind(thisArg){
if(typeof this !== 'function'){
throw new TypeError(this + ' must be a function');
}
// 存储调用bind的函数本身
var self = this;
// 去除thisArg的其他参数 转成数组
var args = [].slice.call(arguments, 1);
var bound = function(){
// bind返回的函数 的参数转成数组
var boundArgs = [].slice.call(arguments);
var finalArgs = args.concat(boundArgs);
// 判断bound函数是否进行 new 调用,其实this instanceof bound判断也不是很准确。
// es6 new.target就是解决这一问题的。
if(this instanceof bound){
// 开始模拟new的调用
// 这里是实现上文描述的 new 的第 1, 2, 4 步
// self可能是ES6的箭头函数,没有prototype,所以就没必要再指向做prototype操作。
if(self.prototype){
// ES5 提供的方案 Object.create()
// bound.prototype = Object.create(self.prototype);
// 这是个ployfill
function Empty(){} // 1.创建一个全新的对象
Empty.prototype = self.prototype; // 2.并且执行[[Prototype]]链接
bound.prototype = new Empty(); // 4.通过`new`创建的每个对象将最终被`[[Prototype]]`链接到这个函数的`prototype`对象上。
}
// 3.生成的新对象会绑定到函数调用的`this`。
var result = self.apply(this, finalArgs);
// 这里是实现上文描述的 new 的第 5 步
// 5.如果函数没有返回对象类型`Object`(包含`Functoin`, `Array`, `Date`, `RegExg`, `Error`),
// 那么`new`表达式中的函数调用会自动返回这个新的对象。
var isObject = typeof result === 'object' && result !== null;
var isFunction = typeof result === 'function';
if(isObject || isFunction){
return result;
}
return this;
}
else{
// apply修改this指向,把两个函数的参数合并传给self函数,并执行self函数,返回执行结果
return self.apply(thisArg, finalArgs);
}
};
return bound;
}