为何要设计this关键字
目的:指向函数运行时所在的环境
1
| var obj = { getName:function(){return this.name} }
|
解释:
- 当对象的属性是一个
函数的时候,会把函数单独保存在堆中,然后把函数的地址赋值给对象属性。
- 而js是允许
在函数体内引用当前环境的其他变量,所以当函数在不同的运行环境执行的时候,需要this来获取函数内的当前运行环境。
如何判断this所指的环境变量
默认绑定
非严格模式
非严格模式下this指向全局对象
1 2 3 4 5 6
| var name = 'lcb'; function foo() { console.log(this.name); }
foo();
|
严格模式
严格模式下,不能将全局对象window作为默认绑定,this会绑定到undefined
1 2 3 4 5 6 7
| 'use strict'; function foo(){ console.log(this.name) } var name = 'lcb' foo()
|
严格模式调用不会影响绑定
1 2 3 4 5 6 7
| function foo(){ console.log(this.name) } var name = 'lcb' 'use strict' foo()
|
node环境下
node环境下不会把变量挂载到全局对象上。因为每个js文件都有自己的作用域
1 2 3 4 5 6 7
| var name = 'lcb'; function foo() { console.log(this); console.log(this.name); }
foo();
|
隐式绑定
函数作为对象的属性,通过对象属性执行函数时候,此时隐式绑定规则会将this绑定到对象上:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| var name = 'lcb'; function foo() { console.log(this.name); }
var obj = { name: 'lql', foo, user:{ name:'userName', foo } }
foo();
var foo2 = obj.foo;
foo2();
obj.foo(); obj.user.foo()
|
结论:只有当作为对象属性调用的时候才会指向该对象
显式绑定
通过call apply bind显式绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| var name = 'lcb'; function foo() { console.log(this.name); }
const obj = { name:'objName' }
const obj2 = { name:'objName2' }
foo.call(obj) foo.call(obj2) foo.call()
|
new绑定
分四种情况:
- new了一个对象
- 返回了一个对象
- 返回了基本数据类型
new了一个对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| var name = 'global'
function Foo(name){ this.name = name this.getName = function(){ console.log(this.name) } }
Foo.prototype.getName2 = function(){ console.log(this.name) }
const newFoo = new Foo('new lcb') newFoo.getName() newFoo.getName2()
|
返回了一个对象
1 2 3 4 5 6 7 8 9 10 11 12 13
| function Foo1(name){ this.name = name return { name:`${name}aaa`, getName:function(){ return this.name } } }
const a = new Foo1('lcb') a.getName()
|
返回了基本数据类型
与返回对象的不同点:new过程中,如果construtor返回的是对象,则返回该对象,否则返回new出来的对象,所以返回基本数据类型可以拿到name
1 2 3 4 5 6 7
| function Foo(name) { this.name = name; return 'hi' }
const a = new Foo('lcb') console.log(a.name)
|
箭头函数
一句话:箭头函数this和外层的this(全局/函数作用域)作用域一致。
例1:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const a = { name:'a', getName:()=>{ console.log(this.name) } }
a.getName()
const b = { name:"b" }
a.getName.call(b)
|
this被绑在了全局作用域下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| function foo() { setTimeout(() => { console.log(this.name); }, 0); }
function foo2(){ setTimeout(function(){ console.log(this.name) },0) }
var name = 'global';
const obj = { name:'lcb' }
foo.call(obj); foo2.call(obj)
|
分析:箭头函数this和外层的函数作用域中的this保持一致,其中foo中的this指向了obj对象,所以箭头函数中的this指向obj对象。
把foo转化为ES5
1 2 3 4 5 6 7
| function foo() { var _this = this;
setTimeout(function () { console.log(_this.name); }, 0); }
|