理解JavaScript中的this指向

1、常规函数中this

this是使用常规方法调用函数时(call)传递的第一个参数,它能够在函数调用时修改,在函数没有调用的时候,this的值是没法肯定的。javascript

1. 纯粹的函数调用

常见写法(简写):java

function test(name) {
    console.log(name)
    console.log(this)
}
test('Jerry')  //调用函数
复制代码

完整写法:函数

function test(name) {
    console.log(name)
    console.log(this)
}
test.call(undefined, 'Tom')
复制代码

若是你传的context 是 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)ui

2. 对象中函数的调用

默认thisthis

const obj = {
    name: 'Jerry',
    greet: function() {
        console.log(this.name)
    }
}
obj.greet()  //第一种调用方法(语法糖)
obj.greet.call(obj) //第二种调用方法
复制代码

手动指定thisspa

const obj = {
    name: 'Jerry',
    greet: function() {
        console.log(this.name)
    }
}
obj.greet.call({name: 'Spike'})  // Spike
复制代码

3. 构造函数中this

构造函数里的this稍微有点特殊,每一个构造函数在new以后都会返回一个对象,这个对象就是this,也就是context上下文。code

function Test() {
    this.name = 'Tom'
}
let p = new Test()
console.log(typeof p)  // object
console.log(p.name)    // Tom
复制代码

new关键字会建立一个空的对象,将this指向这个空对象,这样的话函数内部的this就会被这个空的对象替代。对象

当this碰到return时继承

function fn() {  
    this.user = 'Jerry';  
    return {};   // undefined
    return function(){};  // undefined
    return 1;  // Jerry
    return undefined;  // Jerry
}
var a = new fn;  
console.log(a.user); 
复制代码

若是返回值是一个对象,那么this指向的就是那个返回的对象,若是返回值不是一个对象那么this仍是指向函数的实例。ip

function fn() {  
    this.user = 'Jerry';  
    return null;
}
var a = new fn;  
console.log(a);  // fn {user: "Jerry"}
复制代码

虽然null也是对象,可是在这里this仍是指向那个函数的实例,由于null比较特殊。

4. window.setTimeout()和window.setInterval()中函数的调用

window.setTimeout()和window.setInterval()的函数中的this有些特殊,里面的this默认是window对象。

2、箭头函数中的this

MDN官方文档:箭头函数不会建立本身的this,它只会从本身的做用域链的上一层继承this。

1. 箭头函数的特性一:继承上层this

不使用箭头函数

const obj = {
	a: function() { console.log(this) }    
}
obj.a()  // {a: ƒ} obj对象
复制代码

使用箭头函数

const obj = {
    a: () => {
        console.log(this)
    }
}
obj.a()  // window
复制代码

2. 箭头函数的特性二:不能用call方法修改里面的this

例子

const obj = {
    a: () => {
        console.log(this)
    }
}
obj.a.call('123')  // window
复制代码

结合window.setTimeout()

const obj = {
    a: function() {
        console.log(this)
        window.setTimeout(() => { 
            console.log(this) 
        }, 1000)
    }
}
obj.a.call(obj)  //第一个this是obj对象,第二个this仍是obj对象
复制代码

3、多层对象嵌套里函数的this

例子1

const obj = {
    a: function() { console.log(this) },
    b: {
    	c: function() {console.log(this)}
	}
}
obj.a()  // obj对象, 至关于obj.a.call(obj)
obj.b.c() // obj.b对象, 至关于obj.b.c.call(obj.b)
复制代码

例子2

const obj = {
    a: function() { console.log(this) },
    b: {
    	c: () => {console.log(this)}
	}
}
obj.a()   // obj对象
obj.b.c()  // window!!
复制代码

window对象就是它的上一层this,此例中的多层嵌套只是对象嵌套,这时候没有做用域链的嵌套,实际上对箭头函数来讲,仍是只有本身一级的做用域,和上一层的window做用域

例子3

function fn0() {
    return {
        fn1: function () {
             var obj = {
                a: function() { console.log(this) },
                b: {
        	        c: () => console.log(this)
    	        }
    	    }
    	    return obj;
        }
    }
}

fn0().fn1().b.c() // 获得{fn1: f} fn1对象
复制代码

在ES5中,只有全局做用域和函数做用域,并无块级做用域,因此这里箭头函数仍然绑定外层this值,而非根做用域

相关文章
相关标签/搜索