代码信息来自于http://ejohn.org/apps/learn/。
new做了什么?
function Ninja(){
this.name = "Ninja";
} var ninjaA = Ninja();
console.log( ninjaA, "undefined,ninja并不是实例化" ); var ninjaB = new Ninja();
console.log( ninjaB.name == "Ninja", "true,在实例化里存在name属性" )
对一个函数进行new操作,这就是实例化。
上述代码的流程为,创造一个临时对象,继承Ninja.prototype对象,执行函数Ninja,一开始将上下文this设置为临时对象。没有return语句,返回这个临时对象。
我们的上下文this指向实例化对象
function Ninja(){
this.swung = false; // Should return true
this.swingSword = function(){
this.swung = !this.swung;
return this.swung;
};
} var ninja = new Ninja();
console.log( ninja.swingSword(), "调用实例对象方法" );
console.log( ninja.swung, "引用实例对象属性" ); var ninjaB = new Ninja();
console.log( !ninjaB.swung, "确定this引用的属性是实例化对象的属性,实例化对象彼此不影响." );
习题:增加一个方法,可以给ninja一个name属性
function Ninja(name){
//补足
} var ninja = new Ninja("John");
console.log( ninja.name == "John", "在初始化时name属性就被设置" ); ninja.changeName("Bob");
console.log( ninja.name == "Bob", "name值成功修改" );
向实例化对象增加一个新的属性和方法
function Ninja(name){
this.changeName = function(name){
this.name = name;
}
this.changeName(name)
} var ninja = new Ninja("John");
console.log( ninja.name == "John", "在初始化时name属性就被设置" ); ninja.changeName("Bob");
console.log( ninja.name == "Bob", "name值成功修改" );
当没有使用new时会发生什么?
function User(first, last){
this.name = first + " " + last;
} var user = User("John", "Resig");
console.log( typeof user == "undefined", "因为没有new,所以User作一般函数调用,没有返回值" );
function User(first, last){
this.name = first + " " + last;
} window.name = "Resig";
var user = User("John", name); console.log( name == "John Resig", "全局属性被覆盖" );
当没有new时,它其实就是一般的函数调用,遵循函数调用的本质。
确保在错误的情况下仍然使用对象实例化
function User(first, last){
if ( !(this instanceof User) )
return new User(first, last);
this.name = first + " " + last;
} var name = "Resig";
var user = User("John", name); console.log( user, "即使没有使用new,仍然可以正确实例化" );
console.log( name == "Resig", "实例化属性正常" );
通过判断this不是构造函数User的实例化对象,重新实例化,这是一个可以不使用new进行实例化的技巧。
习题:有没有更加基因化的方法做同样的事情?
function User(first, last){
if ( !(this instanceof ___) )
return new User(first, last);
this.name = first + " " + last;
} var name = "Resig";
var user = User("John", name); console.log( user, "即使没有使用new,仍然可以正确实例化" );
console.log( name == "Resig", "实例化属性正常" );
用arguments.callee实现
function User(first, last){
if ( !(this instanceof ___) )
return new User(first, last);
this.name = first + " " + last;
} var name = "Resig";
var user = User("John", name); console.log( user, "即使没有使用new,仍然可以正确实例化" );
console.log( name == "Resig", "实例化属性正常" );
arguments.callee引用的是函数本身。