-
apply()
- 参数:运行函数的作用域(必须传入),参数数组(arguments对象或者Array实例)
-
call()
- 参数:运行函数的作用域(必须传入),参数必须逐个列举出来
-
这两种方法没有什么不同,就是取决你给函数传递的参数的方式,真正的作用是扩充函数运行的作用域,对象不需要与方法有任何的耦合关系。
window.color='red';
var o={color:'blue'}
function sayColor(){
alert(this.color)
}
sayColor(); // red
sayColor.call(this); // red
sayColor.call(o); // blue
-
bind()
- 创建一个函数的实例,其
this
值会绑定到传给bind()
函数的值。 - 即使在全局作用域调用这个函数,函数里面的
this
也是指向绑定的函数的this
- 创建一个函数的实例,其
window.color='red';
var o={color:'blue'}
function sayColor(){
alert(this.color)
}
var objectS=sayColor.bind(o);
objectS(); // blue 全局调用也是执行o对象中的this
bind()
预处理机制,就是先把函数中的this和参数都改变,然后返回一个改好的函数,不会立即执行;在需要用的时候,调用
简单使用bind()
var oDiv=document.getElementById('div');
var obj={};
function fn(n,m){
console.log(this,(n+m)); // object{} 5
}
oDiv.onclick=fn.bind(obj,2,3)
上面的代码说明了bind()
的预处理机制,首先bind()
是函数Function
身上原型上面的方法,可以提供给实例调用;当我们直接调用的fn(2,3)
的时候,所打印的值是window 5
,可见原先的函数里面的this
是指向window
的,调用bind()
,把函数中的this
改为obj
,并且为函数传递了两个参数,此时改好的函数已经赋值给了点击事件,等待点击事件的触发,来执行函数,即不会立即执行。
封装bind()
前面说过,
bind()
是函数原型上面的方法,可以提供给函数实例使用,封装一个方法,首先是为了解决兼容性问题,其次是希望实例对象拿来就使用,最好是封装在原型上面,成为一个公共的方法;既然是改变this
执行,那么bind()
中第一个参数是必须传递的,使改变后的this
指向谁
// 这个方法的主要目的是改变this指向
Function.prototype.myBind=function(thisArg){
// 获取除thisarg的其余参数,返回数组
// 首先使call前面的函数整体中的this指向arguments集合,接着使用slice方法截取索引值为1到agreement集合末尾的所有数据,组成一个数组赋值给outArg
var outArg=Array.prototype.slice.call(arguments,1);
// 判断支持bind方法的浏览器和不支持的浏览器
if('bind' in Function.prototype ){
// 如果bind属性在原型对象上面
return this.bind.apply(this,[thisArg].concat(outArg));
}
// 不支持bind属性方法在原型上面
var _this=this;
return function(e){
//arguments:用来接收实参的
var innerArg=arguments.length==0?window.event||e;//innerArg用来拿的是事件对象;
_this.apply(thisArg,outArg.concat(innerArg));
//把一个已经改好this指向和参数的函数立即执行了:注意:只有匿名函数被调用,_this.apply这个函数才会立即执行;
}
};
- 使用
bind
来求出鼠标点击的位置,bind
的使用
注意点:
- 考虑bind封装在哪里:Function.prototype.自定义的函数名
- bind中this的指向:实例
- bind中的参数问题:第一个参数是必须传递的;改变this的指向的
- bind的返回值:已经改好的this和传好的匿名函数
concat()是数组的方法,要对象转为数组:[object]==array
var oDiv=document.getElementById('div');
Function.prototype.myBind=function(thisArg){
// 拿到除了this之外的其他参数;返回一个数组,只有数组有slice方法,所以使用了数组的原型来获取slice方法
//arguments的个数是按照传递参数个数来计算的
// 先把call前面函数中的this改为arguments,然后传递参数1,
// 接着slice方法把arguments中的类数组截取除this后面的数组返回给outArg
var outArg=Array.prototype.slice.call(arguments,1);
// 浏览器支持bind方法,就使用浏览器的方法,不行就自己封装
if('bind' in Function.prototype){
return this.bind.apply(this,[thisArg].concat(outArg));
}
// 处理不支持bind方法的浏览器
var _this=this;
return function(e){
// 注意this的指向
var innerArg=argumrnts.length==0?window.event||e;
// 改变这个匿名函数的this指向
_this.apply(thisArg,outArg.concat(innerArg));// 传递的参数:2,3,event事件对象
}
};
function fn(n,m){
// 获取了事件对象 arguments中包括 2,3 event
var e=arguments[2];
console.log(e.clientX, e.clientY)
console.log(this, (n+m)) //obj{} 5
}
var obj={};
// 把fn中的this改为obj{}
oDiv.onclick=fn.myBind(obj,2,3);
网友评论