关于JavaScript中的this指向总结

来源:关于JavaScript中的this指向总结

关于JS中this指向问题,简单地说就是:哪个对象调用了函数,函数中的this就指向这个对象。按以下几种情况进行讨论:

1. 普通函数调用

var num = 10
function fun1(){
    console.log(this) /* Window */
    console.log(num) /* 10 */
}
fun1()
/* 
相当于: window.fun1()
*/

这种情况下,我们直接使用fun1()调用函数,其实就是window.fun1(),所以this就是指向的是调用函数的对象——window对象。

2. 对象函数调用

var num = 10
var obj={
    a:12,
    fn:function(){
        cons.log(this) /* {a: 12, fn: f} */
        console.log(this.a)  /* 12 */
        console.log(this.num) /* undefined */
    }
}
obj.fn()

可以看到调用fn函数的是obj对象,所以this指向的是obj对象,obj对象中没有num,所以打印出来是undefined。

3. 构造函数调用

function Person(name,age){
	this.name = name
	this.age = age
}
var p = new Person('tanjia','18')
/*
	上一步相当于:
	p.name = 'tanjia'
	p.age = '18'
*/
console.log(p) /* Person {name: "tanjia", age: "18"} */

构造函数就是用new 操作符去调用一个函数,这个构造函数内部的this指向新的实例,如:

var p = new Person('tanjia','18')

过程中this指向p。

关于new操作符创建对象时发生的事情:  

第一步: 创建一个Object对象实例

第二步: 将构造函数的执行对象赋给新生成的这个实例

第三步: 执行构造函数中的代码

第四步: 返回新生成的对象实例

4. apply、call、bind调用

apply,call,bind都是来改变this的指向,它们的第一个参数是this指向的那个对象,但是apply接受的第二个参数是数组,call和bind接受的参数是一系列单独的变量。
apply与call立即执行
bind返回一个函数,如果要执行需要再调用

例如:

var obj = {
	a:1,
	b:2,
	add(name) {
		console.log(this.a + this.b)
		console.log(name)
	}
}

var a = {
	a:2,
	b:2,
}
var b = {
	a:4,
	b:2,
}
var c = {
	a:5,
	b:6,
}
/* this指向a对象,2+2=4 */
obj.add.call(a,"call") /* 4 call */

/* this指向b对象,4+2=6 */
obj.add.apply(b,["apply"]) /* 6 apply */

/* this指向c对象,5+6=4 */
obj.add.bind(c,"bind")() /* 11 bind */

从上面的代码中可以看出,我们利用call、apply、bind来改变this指针的指向,传入的第一个参数即是this的指向。

5. 箭头函数调用

箭头函数没有this, 它的this是继承而来,默认指向在定义它时所处的对象(宿主对象), 而不是执行时的对象。

var obj = {
	a:10,
	b:function(){
		console.log(this) /* {a: 10, b: ƒ} */
		setTimeout(function(){
			console.log(this) /* Window */
			console.log(this.a) /* undefined */
		})
	}
}
obj.b()

通过上面代码可以看到,函数obj.b()中的this指向的是obj这个对象,而在setTimeout中函数是普通函数,它的this指向的是window对象。

现在,我们将setTimeout中的函数改为箭头函数,上述中我们知道箭头函数没有this,this是继承而来。

var obj = {
	a:10,
	b:function(){
		console.log(this) /* {a: 10, b: ƒ} */
		setTimeout(()=>{
			console.log(this) /* {a: 10, b: ƒ} */
			console.log(this.a) /* 10 */
		})
	}
}
obj.b()

可以看到,箭头函数中的this指向了obj对象(继承了外部的this),可以访问对象中的元素。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章