关于this
前端中this是个老生常谈的问题,总是说不清道不明,看这里。
this只能用在函数里面,相信全世界的人都知道。
this就是函数在被执行的时候,产生的执行上下文(context)。
this的大致用法,相信接触过前端的同学都知道,无非以下5种。
1、 function test(){
console.log(this);
}
test(); //不是对象的属性,直接执行
2、 var object = {
test: test() {
console.log(this);
}
}
object.test(); //作为对象的属性被调用
3、 test.call(object); // apply用法差不多
4、 Function test() {
this.name = test;
}
5、箭头函数中的this
其中第4种构造函数没什么可说的,构造出了谁,谁就是this。
平常用的最多的也就是前3种,先说第3种情况。最后说第5种。
第3种情况被执行的时候,object
就是作为函数参数
被传入到test()
中,这个函数参数就是this
。
也就是说在test()
被执行的时候,this
就是指向object
。
第1种,第2种情况就是第3种情况的语法糖。
test.call(undefined);
object.test.call(object); //被谁调用指向谁
如果你传的 context 不是一个对象,那么在浏览器中默认是 window 对象。
分析下面的例子:
var name = 'hut';
var obj = {
name : 'lucy',
foo : function() {
console.log(this.name);
}
}
obj.foo();
var otherObj = {
name : 'john',
foo : obj.foo
}
obj.foo();
otherObj.foo();
那么obj.foo();
otherObj.foo();
就是我们上面所说的第2种情况。
先想一下,两次执行后结果是什么。
obj.foo()
其实就是:obj.foo.bind(obj)
,
也就是说函数在被执行的时候,是被obj
调用的,那么函数内的this就是obj
function() {
console.log(this.name); // 输出lucy
}
执行上下文(context)中的this是指向obj
otherObj.foo()
其实就是obj.foo.bind(otherObj)
也就是说函数在被执行的时候,是被otherObj
调用的,那么函数内的this就是otherObj
function() {
console.log(this.name); // 输出john
}
再来看一个例子:
var name = 'Bob';
var obj = {
name = 'lucy',
foo : function() {
console.log(this.name);
}
}
obj.foo();
var otherObj = {
name :'john',
foo : function() {
var testFunc = obj.foo();
testFunc();
}
}
otherObj.foo();
分析:
执行otherObj.foo();
后,接着执行obj.foo();
,也就是说执行下面的函数。
那么这个函数是被谁调用的呢,谁也没有调用这个函数obj.foo()
前面谁也没有。
也就是obj.foo.bind(undefined);
,
function() {
console.log(this.name); // 输出Bob
}
最后看一个例子:
var name = 'Bot';
var obj = {
name : 'lucy',
showName: function() {
console.log(this.name)
},
foo : function() {
(function(callback) {
callback();
})(this.showName)
}
}
obj.foo();
分析:
执行obj.foo();
后,this.showName
中的this就是obj,
也就是将obj.showName;
传给cb,由于是立即执行函数,
则执行callback();
也就是执行下面的函数
那么这个函数是被谁调用的呢,谁也没有调用这个函数callback
前面谁也没有。
也就是obj.showName.bind(undefined);
,输出Bob。
function() {
console.log(this.name); // 输出Bob
}
总结:this被谁调用指向谁,没有被调用的情况下,浏览器默认为window。
特殊情况:setTimeout
,setInterval
,匿名函数执行的时候,
函数体内的this为全局对象window。
最后说第5种,箭头函数中的this。
箭头函数内部并没有实现绑定this的机制,其实箭头函数并没有自己的this,
箭头函数内部的this总是指向父级作用域。
什么意思呢,看个例子。
var name = 'Bob';
var obj = {
name : 'a',
showName: () => {
console.log(this.name);
}
}
obj.showName(); // Bob
分析:obj.showName()
是在全局作用域下被调用的,然后执行下面的函数。
() => {
console.log(this.name);
}
由于箭头函数中的this,总是指向父级作用域
。obj.showName()
是在全局作用域下被调用的,不是obj,obj啥也不是。
所以输出Bob。
call、apply和bind的区别
function add(a,b,c) {
console.log(this);
return a+b+c;
}
以上3个方法都是函数的方法,call和apply都可以改变函数this,传递的参数方式不同。
call一个一个传递,add.call(obj, 1,2,3);
apply以数组的方式传递,add.apply(obj, [1,2,3]);
,更方便。
bind也可以改变函数内部的this,它还可以传递固定参数,var fix = add.bind(null, 100);
函数bind后,与call,apply方法的另一个区别是,
bind便不立即执行,而apply,call会立即执行,add.apply(obj, [1,2,3]);
会立即执行得到结果6,
但是函数bind后,var fix = add.bind(null, 100);
便不会立即执行,fix(2,3)
,调用后才会执行,得到结果105,var fix = add.bind(null, 100);
绑定了第一个参数为100,
相当与固定了第一个参数的值为100,fix
函数被调用后,则只需要传入之后的参数即可。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。