源文转自:https://www.cnblogs.com/Shd-Study/archive/2017/03/16/6560808.html
https://blog.csdn.net/lizeshi125/article/details/53670590
其实是一个很简单的东西,认真看十分钟就从一脸懵B 到完全 理解!
先看明白下面:
var name = '小王', age = 17;
var obj = {
name: '小张',
objeAge: this.age,
myFun: function () {
console.log(this.name + "年龄" + this.age);
}
}
obj.objAge;//17
obj.myFun()//小张年龄unefied
var fav ='在这';
functin show(){
console.log(this.fav);
}
比较一下这两者this的差别,第一个this指向obj,第二个全局声明的shows()函数 this是window;
var name ='小王',age =17;
var obj={
name:'小张',
objAge:this.age,
myFun:function(){
console.log(this.name+"年龄"+this.age);
}
}
var = db{
name:'德玛',
age:99
}
obj.myFun.call(db); //德玛年龄99
obj.myFun.apply(db); //德玛年龄99
大概可以知道为什么需要这些?主要是因为this,来看看this干的好事。
再来看看下面的代码:
box.onclick = function(){
function fn(){
alert(this);
}
fn();
};
我们原本以为这里面的this指向的是box,然而却是Window。一般我们这样解决:
box.onclick = function(){
var _this = this;
function fn(){
alert(_this);
}
fn();
};
将this保存下来。
还有一些情况,有时我们想让伪数组也能够调用数组的一些方法,这时call、apply、bind就派上用场了。
我们先来解决第一个问题修复this指向。
box.onclick = function(){
function fn(){
alert(this);
}
fn();
};
改成如下:
box.onclick = function(){
function fn(){
console.log(this);
}
fn.call(this);
};
很神奇吧,到这里我们可以总结得出,call的作用就是改变this的指向的,第一个传的是一个对象,就是你要借用的那个对象。
fn.call(this);
这里的意思是让this去调用fn这个函数,这里的this是box,box调用fn,这句话非常重要,我们知道this它始终指向一个对象,刚好box就是一个对象。那么fn里面的this就是box。
这句话在某些情况下是可以简写的,比如:
box.onclick = function(){
var fn = function(){
console.log(this); //box
}.call(this);
};或者
box.onclick = function(){
(function(){
console.log(this);
}.call(this)); //box
};
call和apply、bind都是用来改变this的指向的,但也有一些小小的差别。下面我们来看看它们的差别在哪:
function fn(a,b,c,d){
console.log(a,b,c,d);
}
//call
fn.call(null,1,2,3);
//apply
fn.apply(null,[1,2,3]);
//bind
var f = fn.bind(null,1,2,3);
f(4);
结果如下:
1 2 3 undefined
1 2 3 undefined
1 2 3 4
前面说过第一个参数传的是一个你要借用的对象,但这么我们不需要,所有就传了一个null,当然你也可以传其他的,反正在这里没有用到,除了第一个参数后面的参数将作为实际参数传入到函数中。
call就是挨个传值,apply传一个数组,bind也是挨个传值,但和call和apply还有一些不同,使用call和apply会直接执行这个函数,而bind并不直接执行,而是将绑定好的this重新返回一个新函数,什么时候调用由你自己决定。
var objName = {name:'JS2016'};
var obj = {
name:'0 _ 0',
sayHello:function(){
console.log(this.name);
}.bind(objName)
};
obj.sayHello();//JS2016
这里也就是为什么我要用bind的原因,如果用call的话就会报错了。自己想想这个sayHello在obj都已经执行完了,就根本没有sayHello这个函数了。