this是什么?segmentfault
理论上this是执行上下文的一个属性,this的值在进入到执行上下文的时候就已经肯定了,且不会再改变。这一点很重要。数组
this的做用?app
this 的机制提供了一个优雅的方式,隐式地传递一个对象,这可让函数设计的更加简洁,而且复用性更好。函数
new绑定,this指向由new建立的对象this
显示绑定,this指向apply或者call函数的第一个参数设计
隐式绑定,this指向函数的调用者。code
默认绑定,严格模式下指向undefinded,非严格模式this指向全局对象。对象
箭头函数绑定,this指向箭头函数外边包裹的普通函数作用域
当用new建立一个新的对象的时候,this指向了由new关键字声明建立的对象。get
class Person(name){ constructor(name){ this.name = name; } showThis(){ return this; } } var p1 = new Person('zhang'); var p2 = new Person('zhao'); console.log(p1.showThis() === p1); //true console.log(p2.showThis() === p2); //true console.log(p1.showThis() === Persion) //false
能够看到,这种状况下this的值指向了由new建立的对象的引用。this会被绑定到这个对象上去。
所谓的显式绑定,指的是经过apply或者call方法的第一个参数。
call和apply的不一样,两个方法的第一个参数都是this赋给的对象。不一样在于,以后的参数被看成call方法的形参依次传进去,而apply则是接受一个数组。
看代码:
function foo(){ console.log(this === obj); //true console.log(this.a === 2); //true } var obj = { a:2 } foo.call(obj);
隐式绑定用的次数比较多。一个最重要的特色就是,this的指定顺序和在哪里定义没有关系,而是取决于调用者。
严格意义来讲,this是上下文里的一个属性(存放各类变量的变量对象一样也是上下文里的属性),this的值老是指向当前上下文的父级上下文,其实也就是当前上下文的调用者。
看代码:
//第一个简单的例子 var obj = { a : 1, foo : function(){ console.log(this === obj); //trun console.log(this.a === 1); //true }, bar : bar } //假如把一个属性定义在对象外边 function bar(){ console.log(this === obj); //true } obj.foo(); obj.bar(); //都是true
再来一个例子
function bar(){ console.log(this === obj1); console.log(this === obj2); } function foo(){ console.log(this === obj1); console.log(this === obj2); } var obj1 = { bar: bar, foo: foo } var obj2 = { bar: obj1.bar, foo: obj1.foo, } obj1.foo(); //true false obj2.foo(); //false true obj1.bar(); //true false obj2.foo(); //false true
很简单,foo和bar两个方法分别由obj1和obj2调用,哪怕obj2中的foo和bar是obj1的也不要紧,与在哪里定义没有关系,纯粹看是看谁调用的,obj2.foo()就是obj2调用的foo方法,因此,这个时候this指向obj2。
多说一句,若是既有显示绑定又有隐式绑定,固然是以显示绑定为准。
这种状况下,this不属于任何一个函数方法内,即在全局做用域下,这种状况下称为默认绑定。
非严格模式下,这个时候this值为window全局对象。
function foo(){ console.log(this === window); } foo();
严格模式下,this的值是undefined
"use strict"; function foo() { console.log( this === undefined ); } foo(); // true foo.call(undefined); // true foo.call(null); // false
箭头函数实际上是一个语法躺,箭头函数的里的this指向包裹箭头函数的那个函数的this值。很好理解。
// ES6 function foo() { setTimeout(() => { console.log(this === obj); // true }, 100); } const obj = { a : 1 } foo.call(obj); // ES5 function foo() { var _this = this; setTimeout(function () { console.log(_this === obj); // true }, 100); } var obj = { a : 1 } foo.call(obj);
用伪代码的形式来表示
if (`newObj = new Object()`) { this = newObj } else if (`bind/call/apply(thisArgument,...)`) { if (`use strict`) { this = thisArgument } else { if (thisArgument == null || thisArgument == undefined) { this = window || global } else { this = ToObject(thisArgument) } } } else if (`Function Call`) { if (`obj.foo()`) { // base value . Reference = base value + reference name + strict reference // 例外: super.render(obj). this = childObj ? this = obj } else if (`foo()`) { // 例外: with statement. this = with object this = `use strict` ? undefined : window || global } }