JavaScript开发中this给程序员挖的坑,你遇到过吗?

对于程序员来说,this这个关键字应该是再熟悉不过了,在C++、C#以及Java中,它的身影随处可见,this也可以说是编程语言JavaScript的精髓,但是一定也有不少JavaScript开发者都遇到过this的陷阱。

在C++、C#、Java中,this拥有十分明确的含义,就是单纯指向当前的对象实例,但是,在动态编程语言JavaScript中,相同的this写法,却有不同的含义。

JavaScript开发中this给程序员挖的坑,你遇到过吗?

JavaScript中的this代表函数运行时自动生成的一个内部对象,只能在函数内部使用。并且,你不能在创建统计this的时候就确定它,而应该在函数执行时进行确定,所以,一不留神,你就会掉进意想不到的坑!

0、谁调用了就谁来负责

我们先来看看代码:

var name = 'a';

var obj = {

name: 'b',

getName: function() {

console.log(this.name);

}

};

obj.getName(); // b

var getName = obj.getName;

getName(); // a

var obj2 = (function() {

return function() {

console.log(this.name);

}

})();

obj2(); // a

首先,obj.getName()打印出来b,因为,obj调用了getName(),所以其this指向obj,this.name就是b。

其次,getName()打印出a的原因:理由是此时的obj并不调用getName(),而是全局变量window,因此,结果是a

最后,obj2中,因为采用了立即执行函数,它返回一个函数,而当我们调用时,调用它的也是全局变量window,所以打印结果也是a。

需要注意的是,匿名函数内的this是指向window的,更准确的说是指向调用者。

JavaScript开发中this给程序员挖的坑,你遇到过吗?

1、必须了解new的过程

function Test() {

console.log(this.name);

}

Test(); // a

var test = new Test(); // undefined

function Test2() {

this.name = 'c';

}

var test2 = new Test2();

console.log(test2.name); // c

为什么这个例子最终打印出来的是c呢?这里new的过程不可忽略,new Test2() 其实执行了三步动作:

首先,创建一个空对象obj(var obj = {};),然后,将这个空对象的[[Prototype]](__proto__)成员指向了Test2函数对象prototype成员对象最后,将Test2函数对象的this指针替换成obj:

obj.__proto__ = Test2.prototype;

Test2.call(obj);

当没有显式返回值或者返回为基本类型、null时,默认将 this 返回(参考2)

因此,在这个例子中,当你使用new的时候,函数内部的this指向已经改变了,不再指向window。

主要应该搞清楚new的过程,然后就知道打印出c的原因了。

JavaScript开发中this给程序员挖的坑,你遇到过吗?

2、奇怪的return

看过上面的例子后,你是否觉得已经掌握了new的函数内的this指向?千万别掉以轻心,在JavaScript中,多的是例外,如:

function Test3() {

this.name = 'd';

return {};

}

var test3 = new Test3();

console.log(test3.name); // undefined

function Test4() {

this.name = 'd';

return 1;

}

var test4 = new Test4();

console.log(test4.name); // d

可以再试试return 'd' | null | undefined中的一个或更多类型。

结论:如果return的是一个对象(null除外),那么this指向的这个对象,否则this依旧指向实例对象。


分享到:


相關文章: