初窥关键字new的真容

假设我们没有new操作符。

1.创建对象

没有new操作符,我们怎样创建一个对象?当然可以使用如下代码。

function Empolyee(name){  
    this.name = name;  
    this.getName = function(){return this.name};  
}  
var employee = {};  
Employee.call(employee,'Jack');

我们用字面量方法创建一个employee对象,然后通过call()将构造函数的this指向employee对象。这样就完成了一个对象的创建。


2.实现继承

JavaScript是基于原型的面向对象设计,所以我们采取原型继承。即将子类中prototype属性设置为父类的对象,达到继承的目的。我们修改以上代码。

var topObject = {  
    __version__ : 1.0;  
};  
  
function Empolyee(name){  
    this.name = name;  
    this.getName = function(){return this.name};  
}  
var employee = {};  
employee.__proto__ = topObject;  
Employee.call(employee,'Jack');  
  
function Coder(name,language){  
    this.name = name;  
    this.language = this.language;  
    this.getLanguage = function(){return this.language};  
}  
  
var coder = {};  
coder.__proto__ = employee;  
Coder.call(coder,'Coder Jack','Java');

在创建employee的同时将自身的prototype属性设置为topObject,继承employee的coder则将prototype设置为employee。这样继承的任务也完成了。


3.函数封装

现在我们可以创建对象,并实现让它继承某个对象,但整个过程需要三行代码。现在我们进一步优化,把三行代码封装成一个newInstance()函数以备复用。

function sliceArguments(argumentsObj,n){  
    var args = [];  
    for(var i=0;i<argumentsObj.length;i++){  
        if(i>=n){  
            args.push(argumentsObj[i]);  
        }  
    }  
}  

function newInstance(prototype,constructor){  
    var obj = {};  
    obj.__proto__ = prototype;  
    constructor.apply(obj,sliceArguments(arguments,2));  
}  

var employee = newInstance(topObject,Employee,'Jack');  
var coder = newInstance(employee,Coder,'Coder Jack','Java');


4.缩减函数

  仔细一看,newInstance()的参数可以更少,我们可以把原型对象prototype作为属性放在constructor,那样我们的函数就可以只有一个参数了。属性名就约定为prototype吧。我们修改解释器,把topObject写入语言作为原生的顶级对象;再修改function的源代码,让每一个新建的function都默认具有属性prototype = topObject。 优化后的代码如下。

function newInstance(constructor){  
    var obj = {};  
    obj.__proto__ = constructor.prototype;  
    constructor.apply(obj,sliceArguments(arguments,1));  
    return obj;  
}  
function Employee(name){  
    this.name = name;  
    this.getName = function(){return this.name};  
}  
var employee = newInstance(Empolyee,'Jack');  
var employee2 = newInstance(Empolyee,'Jack2');  
var employee3 = newInstance(Empolyee,'Jack3');  
function Coder(name,language){  
    this.name = name;  
    this.language = language;  
    this.getLanguage = function(){return this.language};  
}  
Coder.prototype = newInstance(Empolyee,'');  
  
var coder = newInstance(Coder,'Coder Jack','Java');  
var coder2 = newInstance(Coder,'Coder Lee','C#');  
var coder3 = newInstance(Coder,'Coder Liu','C++');  
var coder4 = newInstance(Coder,'Coder Liu','JavaScript'); 

到目前为止,我们发现其实我们一路修改过来的newInstance()就是new操作符。


5.理解new function()

function Employee(name){  
    this.name = name;  
    this.getName = function(){return this.name};  
}  
var employee = new Employee('Jack');

分析上面代码。Javascript引入new关键字是为了模仿java创建对象的方式。我们知道,基于原型的语言生成一个步骤有两步,第一步是使用"原型对象"作为"模板"生成新对象,第二步是初始化新对象的内部属性。

我们敢肯定地推断,javascript中的new Employee('Jack');必然做了这两件事情,那么 
1 "原型对象"在哪里? 
2 怎么做到"初始化新对象的内部属性"? 
答案是,Employee.

prototype就是我们要找的"原型对象",通过"以新对象代替this,执行Employee函数"做到了"初始化新对象的内部属性"。 
使用new+function的方式创建对象,其实就是应用我们设计的函数newInstance时的思想。

function newInstance(constructor){  
    var obj = {};  
    obj.__proto__ = constructor.prototype;  
    constructor.call(obj,sliceArguments(arguments,1));  
    return obj;  
}




更多精彩请关注我的BLOG:http://hello13.net/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值