最近忙的要死一下子这么久没写博客,从今天开始争取一周写两篇。
好废话不多说,继续上次的话题。
this中的大坑
相信在用js编程过程中大家都被this坑过,而最容易被坑道的地方就是定时器,上代码:
setTimeout(function(){
console.log(this); //window
}, 1000)
这里的this是window为什么呢,我也不知道,不过按照理论上来说是因为setTimeout没有什么对象调用它,它的this便是window。
解决这个问题也很简单,上代码:
var obj = {
_name: 'abc',
showName: function () {
setTimeout(function () {
console.log(this._name); //undefined
}, 1000);
}
}
如果是像上面那么写一定是undefined,因为在定时器里this是window,而window上并没有_name这个属性。我的解决方法是:
var obj = {
_name: 'abc',
showName: function () {
var that = this;
setTimeout(function () {
console.log(that._name); //undefined
}, 1000);
}
}
定义一个that把this保存起来,在setTimeout要使用this时把this改成that就可以了,其实这种方法在es3中经常会用到,下面在举个例子:
var obj = {
age: 2,
show: function (age) {
age();
}
}
var obj2 = {
age: 3,
show: function () {
obj.show(function () {
console.log(this); //window
})
}
}
obj2.show();
这种在函数中传入函数作为参数的情况是很常见的,这种情况也可以用上面那个方法来解决:
var obj = {
age: 2,
show: function (age) {
age();
}
}
var obj2 = {
age: 3,
show: function () {
var that = this;
obj.show(function () {
console.log(that); //obj2
})
}
}
obj2.show();
像这样的例子还用很多,这里就不一一列举了。
原型链
提到this就不得不说原型链,js不是一个面向对象的语言,但js中有个说法:“一切皆对象”,是对象就有原型,有原型就有原型链:
var str = 'string';
console.log(str.__proto__); // String
var num = 123;
console.log(num.__proto__); // Number
console.log(num.__proto__.__proto__); //
var obj = {
a: 'a'
}
console.log(obj.__proto__); // Object
...
可以看出每种数据类型都有原型,原型上呢?还有原型。这就形成了原型链,而通过this可以访问到原型链的方法和属性,我们这里以对象为例:
var obj = {
age: 12,
show: function () {
console.log(this.toString) // ƒ toString() { [native code] }
}
}
obj.show()
obj并没有toString这个方法,这个方法就是在obj的原型链上访问到的。再举个例子:
var obj = {
age: 12,
toString: 'abc'
show: function () {
console.log(this.toString) // 'abc'
}
}
obj.show()
当obj上有toString时访问的就是obj中的toString也就是说当我们访问对象的属性或者方法时,先在自己身上找,找不到就去自己的原型找,没有再去原型的原型找,以此类推。
今天先写到这里。闪人。。。