JavaScriptWeb前端之路程序员

你不知道的JavaScript之this篇(一)

2017-07-21  本文已影响40人  2f1b6dfcc208

From 《你不知道的JavaScript》上卷

  this关键字是JavaScript中非常复杂的机制之一,它是一个很特别的关键字,被自动定义在所有函数的作用域中,我们平时会经常用到它,但是往往不求甚解,以致于在很多地方滥用this甚至根本弄不清this的真正含义。

function identify(context){
    return context.name.toUpperCase();
}
function speak(context){
    var greeting = "hello,I'm "+ identify(context);
    console.log(greeting);
}
var me = { name:'ht'}
var you = {name:'xm'}
identity(you);//XM
speak(me);//hello,I'm HT

下面使用this来重写这两个函数

function identify(){
    return this.name.toUpperCase();
}
function speak(){
    var greeting = "hello,I'm "+ identify.calll(this);
    console.log(greeting);
}
identify.call(me);//HT
identify.call(you);//XM
speak.call(me);//hello,I'm HT
speak.call(you);hello,I'm XM

通过使用this我们可以在不同的上下文对象中重复使用identify()和speak(),不需要再显示的传入一个上下文对象,也许这个例子太简单了,让你看不出太多的差别,但随着代码的复杂度增加,显示传递上下文会让js代码变得越来越复杂,如果函数可以自动引用合适的上下文对象,我们可以将API设计得更加简洁并且易于复用。

function foo(num){
    console.log("foo:" + num);
    this.count ++;
}
foo.count = 0;
for(let i=0;i<10;i++){
    if(i>5){
        foo(i);
    }
};
//foo:6
//foo:7
//foo:8
//foo:9
console.log(foo.count);//0

很显然,这里的foo(...)被调用了4次,但是foo.count的值并不是预期的4,而是0,说明了这里的this并不是指向函数自身,显然从字面意思来理解this是错误的。执行 foo.count=0时,的确向函数对象添加了一个属性count,但是函数内部的this.count并不是指向当前函数对象的count属性,虽然属性名相同,根对象却不相同,实际上这里的this指向全局对象。
如果并不想深究为什么而只是想要解决问题,可以使用其它方式

function foo(num){
    console.log('foo:'+num);
    data.count++;
}
var data = { count:0 }
for(let i=0;i<10;i++){
    if(i>5){
        foo(i);
    }
};
console.log(data.count);//4    

上面使用了词法作用域来解决问题,显然这是有效的,但它避免了使用this,并没有真正理解this的含义和工作原理。如果要从函数对象内部引用它自身,那只使用this是不够的,一般来说需要通过一个指向函数对象的词法标识符(变量)来引用它。

function foo(num){
    console.log('foo:'+num);
    foo.count++;
}
foo.count=0;
for(let i=0;i<10;i++){
    if(i>5){
         foo(i);
    }
};
console.log(foo.count);//4

然而这种方法同样回避了this的问题,并且完全依赖于变量foo的词法作用域。其实还有一种方法是强制this指向foo函数对象。

function foo(num){
    console.log('foo:' + num);
    this.count++;
}
foo.count=0;
for(let i=0;i<10;i++){
    if(i>5){
        foo.call(foo,i);
    }
}
console.log(foo.count);//4

(2)、指向它的作用域。第二种常见的误解是,this指向函数的作用域。这个问题有点复杂,因为在某种情况下它表现是正确的,但是在其它情况下它却是错误的。需要明确的是,this在任何情况下都不指向函数的词法作用域。在JavaScript内部,作用域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过JavaScript代码访问,它存在于JavaScript引擎内部。

突然想说一句,js真的是门坑爹的语言~

上一篇下一篇

猜你喜欢

热点阅读