@mwumli
2016-03-27T21:14:36.000000Z
字数 1730
阅读 1544
前端
JavaScript
JavaScript 使用 new 操作符来实例化对象, 可能是试图让熟悉基于类继承的开发人员更容易理解,但是这往往开发者产生误会
为此, 后来引进了 Object.create
方法 作为 new
操作符的替代方案, 使用它来创建 JavaScript 对象, 能增添一种更像是基于原型的感觉
为了让更多的对象获取相似的特性, 因此会把相似的特性放在一个对象中, 以此对象为原型来创建新对象, 因此这个 作为原型的对象 就被称为 原型对象
JavaScript 创建对象的方式很多, 构造函数就是其中一种 , 构造函数的缺点是无法共享属性和方法,
但是构造函数有一个属性 prototype
来保存原型对象, 这样就解决了共享属性和方法的问题
在过去, 我们要以某个对象为原型来创建新对象, 需要为构造函数设置原型, 设置属性 prototype
就像下面这样 :
// 定义原型对象
var proto = {
nation : "中国",
sentence : 3
};
// 定义对象的构造函数
var chinesePrisoner = function (name, id) {
this.name = name;
this.id = id;
}
// 使用 `prototype` 属性将构造函数的原型关联到原型对象
chinesePrisoner.prototype = proto;
// 使用 new 运算符创建新对象
var firstPrisoner = new chinesePrisoner("Tom", "12A");
var secondPrisoner = new chinesePrisoner("Jam", "12B");
构造函数配合 prototype
看起来很完美, 其实还是存在很多问题, 这个就不在这里讨论了
有兴趣的话看看 《JavaScript 高级程序设计》 这本书
因为 new
是大多数基于类继承的语言实例化的关键字, 在 JavaScript 中往往让人把类继承和原型继承弄混
后来出现了 Object.create
这个方法来实现原型继承
刚才的那个例子改成下面这样 :
var proto = {
sentence : 3,
provation : 2
};
var firstPrisoner = Object.create(proto);
firstPrisoner.name = "wang";
firstPrisoner.id = "12A";
var secondPrisoner = Object.create(proto);
secondPrisoner.name = "li";
secondPrisoner.id = "12B";
这样也就避免了设置 prototype
引发的一些问题, 而且使用 Object.cteate
给人一种基于某个对象创建的感觉, 应该更符合 JavaScript 原型继承的思想
当前 ECMAScript 引入了
class
关键字, 所以现在完全可以以类继承的方式进行程序设计
上面那段代码虽然避免了构造函数的一些问题, 但是有一些重复的代码而显的不简洁
因此我们可以采用工厂模式来解决这个问题 :
var proto = {
sentence : 3,
provation : 2
};
var makePrisoner = function(name, id) {
var prisoner = Object.create(proto);
prisoner.name = name;
prisoner.id = id;
};
var firstPrisoner = makePrisoner("wang", "12A");
var secondPrisoner = makePrisoner("li", "12B");
工厂函数可以以 make<Object-name>
的形式命名
Object.create
的概念提出的比较晚, 因此对于一些老的浏览器并不兼容
因此, 我们可以这样解决 :
var objectCreate = function( proto ) {
if ( !proto ) return {};
function obj() {};
obj.prototype = proto;
return new obj;
};
Object.create = Object.create || objectCreate;