js的this,被人讲了无数遍。这里我还是想在说一下自己的理解。
首先需要从函数调用开始讲起
es5中有三种函数调用的形式:
func(a1,a2);
obj.child.method(a1,a2);
func.call(context,a1,a2);
其实前两种调用方式都是call的简化版,
func.call(undefined,a1,a2);
obj.child.method.call(obj,a1,a2);
所以
function func(){
console.log(this)
}
func()
等价于
function func(){
console.log(this)
}
func.call(undefined);
因此,this应该指向undefined(node环境),但是在浏览器环境中,window会是默认传入的上下文context对象,所以打印结果为window。
那么,obj.child.method怎么确定this呢?
var obj = {
foo:function(){
console.log(this)
}
}
obj.foo()
等价于
obj.foo.call(obj)
所以this就是你call一个函数时传入的context,这也就是this指向和声明位置无关,与调用位置有关。
- 默认绑定
严格模式下this默认绑定到undefined,非严格模式下this默认绑定到window全局对象。
function hello(){
var name = 'ke';
console.log(this.name);
}
var name = cat;
hello(); //cat,调用的时候是hello的调用者是window
- 隐式绑定
函数的调用位置会判断是否存在上下文对象(context),存在则将this绑定在上下文对象。
一般写在某个对象内部包含一个指向函数的属性,通过这个属性间接引用函数,把this绑定到这个对象上。
function foo(){
console.log(this.name)
}
var person = {
name:'ke',
foo:foo
}
person.foo()//ke
调用位置在person上下文,this.name 相当于person.name
但是也容易丢失绑定对象
function foo(){
return function ke(){
return this.name
}
}
var person = {
name:'ke',
foo:foo
}
var name = 'cat'
console.log(person.foo()())
还有一种隐式就是回调函数。
var a ={
num:10,
add:add
}
var num =20;
function add(){
return this.num + 10
}
function sum(fn){
fn();
}
console.log(sum(add))
或者将定时器传入函数中,解决办法是var that = this
或者箭头函数
- 显式绑定
call apply - new绑定
对象中的this,对象调用自己定义的方法时,this指向这个对象
var obj = {
id:9,
test:function(){
return this.id;
}
}
obj.test();
test在对象obj中,所以函数的运行环境就是obj所在上下文,所以this指向obj。
原型链中的this
getter setter里的this。
es6中引入箭头函数,此时this关键字指向当前函数的词法作用域,与声明位置有关,与调用位置无关。