首页 » 编写高质量代码:改善JavaScript程序的188个建议 » 编写高质量代码:改善JavaScript程序的188个建议全文在线阅读

《编写高质量代码:改善JavaScript程序的188个建议》建议87:分辨this和function调用关系

关灯直达底部

JavaScript的this一直是容易让人误用的关键词,尤其对于熟悉Java的程序员来说,因为JavaScript中的this与Java中的this是有很大不同的。在一个function的执行过程中,如果在变量的前面加上了this作为前缀,如this.myVal,对此变量的求值就从this所表示的对象开始。

this的值取决于function被调用的方式,一共有5种:

❑如果一个function是一个对象的属性,那么在funtion被调用时,this的值是这个对象。

❑如果function调用的表达式包含句点(.)或,那么this的值是句点(.)或之前的对象。如在myObj.func和myObj["func"]中,func被调用时的this是myObj。

❑如果一个function不是作为一个对象的属性,那么在function被调用时,this的值是全局对象。当一个function中包含内部function时,不理解this的正确含义就很容易造成错误,因为内部function的this值与它外部的function的this值是不一样的。


var myObj={

myVal:"Hello World",

func:function{

alert(typeof this.myVal);//string

var self=this;

function inner{

alert(typeof this.myVal);//undefined

alert(typeof self.myVal);//string

}

inner;

}

};

myObj.func;


在myObj函数体内有个内部名为inner的函数,在inner被调用时,this的值是全局对象,因此找不到名为myVal的变量。这时通常的解决办法是将外部function的this值保存在一个变量中(此处为self),在内部函数中使用它来查找变量。

❑如果在一个function之前使用new,则会创建一个新的对象,该funtion也会被调用,而this的值是新创建的那个对象。


function User(name){

this.name=name

};

var user1=new User("Alex");


调用new User("Alex")会创建一个新的对象,以user1来引用,User这个function也会被调用,会在user1这个对象中设置名为name的属性,其值是Alex。

❑如果通过function的apply和call方法来指定它被调用时的this的值,那么apply和call的第一个参数都是要指定的this值,两者不同的是调用的实际参数在apply中是以数组的形式作为第二个参数传入的,而在call中除了第一个参数外其他参数都是调用的实际参数。

JavaScript中并没有Java或C++中的类的概念,而是采用构造器的方式来创建对象。在new表达式中使用构造器就可以创建新的对象。由构造器创建出来的对象有一个隐含的引用指向该构造器的prototype。

所有的构造器都是对象,但并不是所有的对象都能成为构造器。能作为构造器的对象必须实现隐含的Construct方法。如果new操作符后面的对象并不是构造器,会抛出TypeError异常。

new操作符会影响function调用中return语句的行为。当调用function时有new作为前缀,如果返回的结果不是一个对象,那么新创建的对象将会被返回。


function user(name){

this.name=name;

}

function anotherUser(name){

this.name=name;

return{

"badName":name

};

}

var u1=new User("Alex");

alert(typeof u1.name);//string

var u2=new anotherUser("Alex");

alert(typeof u2.name);//undefined

alert(typeof u2.badName);//string


在上面代码中,函数anotherUser通过return语句返回了一个对象,因此u2引用的是返回的那个对象;而函数user并没有使用return语句,因此u1引用的是新创建的User对象。