假设我们没有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/