call()
Function.prototype.newCall = function(){
//将要使用的函数给要指向的target(相当于再target里面添加一个属性,这个属性名为fn,属性值为 this)
var target = arguments[0] || windows
target.fn = this;
var args = [];
for(var i = 1; i < arguments.length; i ++){
args.push('arguments['+ i +']');
}
//执行target下fn这个属性 => target.fn(str);
//eval()会直接将字符串作为表达式/函数进行执行
var result = eval('target.fn(' + args.join(',')+')');
//把创建的fn属性删除
delete target.fn;
return result;
}
复制代码
apply()
Function.prototype.newApply = function(target, arr){
target = target || windows
target.fn = this;
//判断数组是否为空,如果为空直接执行。
if(arr == []){
return target.fn;
delete target.fn;
}else{
var args = [];
for(var i = 0; i < arr.length; i ++){
args.push('arr['+ i + ']');
}
var result = eval('target.fn('+ args.join(',') +')');
delete target.fn;
return result;
}
}
复制代码
call()
和apply()
都是改变this的指向,它们之间只是是传参的形式不同。call()
是字符串的形式,而apply()
的第二个参数是数组的形式。
bind()
var value = 0;
var obj = {
value : 123
};
function show(grade, name, age){
console.log(this.value);
console.log(grade, name, age);
return name + age + value;
}
Function.prototype.newBind = function(){
var target = arguments[0] || window
var self = this;
//console.log(this)-->function show(){}
//newBind 的形参数列表,去掉target。
var args = [].slice.call(arguments,1);
var temp = function(){};
创建一个新函数 newFn
var newFn = function(){
//新函数的参数列表
var _args = [].slice.call(arguments,0);
//判断执行函数是否是构造函数执行的,是的话就用this,
//若不是通过new的方式来执行,而是直接执行的话,就用target
return self.apply(this instanceof temp ? this : target, args.concat(_args));
}
//让this(-->f show(){})和newFn形成关联,确保原型链不被破坏。
temp.prototype = this.prototype;
newFn.prototype = new temp();
//返回新函数
return newFn;
}
var newShow = show.newBind(obj,'三年级');//'三年级' -> args
newShow('kiwi', 18);// 'kiwi', 18 -> _args
//123
//三年级 kiwi 18
复制代码
bind()
和call()/apply()
的不同点简述
1)bind() 是返回一个新的函数。而 call()/apply() 绑定函数后直接执行,且每次执行都要重新绑定。
2)bind() 支持函数拥有预设的初始参数(即,'三年级'),这些参数会排在最前面,传给绑定函数的参数(即,'kiwi', 18)会跟在它们后面。复制代码