红叶何时落水
bind是函数原型对象上的一个方法,用于改变函数的this指向
这个方法会返回一个新函数,新函数可以调用他所绑定的对象的属性。
var name = 'window';
var newThis = { name: 'newThis' };
var showName = (info1, info2) => {
console.log(this, info1, info2);
}
showName('a', 'b');
// 通过bind改变this指向
var newShowName = showName.bind(newThis, 'hello', 'world');
showName = (info1, info2) => {
console.log('new_func');
}
newShowName();
showName('a', 'b');
输出
Window {window: Window, self: Window, document: #document, name: 'window', location: Location, …} a b
Window {window: Window, self: Window, document: #document, name: 'window', location: Location, …} hello world
new_func
bind方法的简易实现
Function.prototype.bind = function (o) {
var self = this, boundArgs = arguments;//bind()方法的返回值是一个函数
return function () {//创建一个实参列表,将传入bind()的第二个及后续的实参都传入这个函数
var args = [], i;
for (i = 1; i < boundArgs.length; i++)args.push(boundArgs[i]);
return self.apply(o, args);
};
};
再者,bind会返回一个新函数,那么就可以蕴含了柯里化的思想,将一些参数的值固定。
var newThis = { name: '可通过改变对象属性改变' };
function showName(info1, info2) {
console.log(this.name, info1, info2);
}
var newShowName = showName.bind(newThis, '外部无法改变,属于该函数不可改变的私有变量');
newShowName('新函数的实参');
newThis.name = '对象属性改变';
newShowName('新函数的实参');
输出
可通过改变对象属性改变 外部无法改变,属于该函数不可改变的私有变量 新函数的实参
对象属性改变 外部无法改变,属于该函数不可改变的私有变量 新函数的实参
call也是函数原型对象上的一个方法,用于暂时改变函数的this指向
会对this指向的对象进行属性的读取,添加,修改,方法的调用
function showName() {
this.id = 2;
this.func_attr = "func_attr";
console.log(this.id + ':' + this.name);
};
var obj = {
id: 1,
name: 'yuguang'
};
showName.call(obj);//=>2:yuguang
console.log(obj);//=>{id: 2, name: 'yuguang', func_attr: 'func_attr'}
call的基本思想,就是将函数暂时绑定到目标对象,然后在目标对象的作用域下执行函数;在函数执行时,函数可以通过this来对对象进行操作。之后,将函数从对象上移除。
Function.prototype.newCall = function(obj) {
obj.new_func = this; //调用newcall的对象是函数foo,this指向函数。现在使obj上有了一个新方法foo
let args = [];
for(let i = 1; i < arguments.length; i++ )
args.push(arguments[i])
let result = obj.new_func(...args);
delete obj.new_func
return result;
}
function foo(x, y) {
this.name = x;
this.attr = y;
return y;
}
let obj = {
name: "obj_name"
}
console.log(foo.newCall(obj, "first", "second")) //=> second
console.log(obj); //=> {name: 'first', attr: 'second'}