[关闭]
@mwumli 2016-03-27T13:14:36.000000Z 字数 1730 阅读 1443

Javascript 中 new 和 Object.creat 的思考

前端 JavaScript


JavaScript 使用 new 操作符来实例化对象, 可能是试图让熟悉基于类继承的开发人员更容易理解,但是这往往开发者产生误会

为此, 后来引进了 Object.create 方法 作为 new 操作符的替代方案, 使用它来创建 JavaScript 对象, 能增添一种更像是基于原型的感觉

原型对象

为了让更多的对象获取相似的特性, 因此会把相似的特性放在一个对象中, 以此对象为原型来创建新对象, 因此这个 作为原型的对象 就被称为 原型对象

JavaScript 创建对象的方式很多, 构造函数就是其中一种 , 构造函数的缺点是无法共享属性和方法,
但是构造函数有一个属性 prototype 来保存原型对象, 这样就解决了共享属性和方法的问题

在过去, 我们要以某个对象为原型来创建新对象, 需要为构造函数设置原型, 设置属性 prototype

就像下面这样 :

  1. // 定义原型对象
  2. var proto = {
  3. nation : "中国",
  4. sentence : 3
  5. };
  6. // 定义对象的构造函数
  7. var chinesePrisoner = function (name, id) {
  8. this.name = name;
  9. this.id = id;
  10. }
  11. // 使用 `prototype` 属性将构造函数的原型关联到原型对象
  12. chinesePrisoner.prototype = proto;
  13. // 使用 new 运算符创建新对象
  14. var firstPrisoner = new chinesePrisoner("Tom", "12A");
  15. var secondPrisoner = new chinesePrisoner("Jam", "12B");

构造函数配合 prototype 看起来很完美, 其实还是存在很多问题, 这个就不在这里讨论了
有兴趣的话看看 《JavaScript 高级程序设计》 这本书

因为 new 是大多数基于类继承的语言实例化的关键字, 在 JavaScript 中往往让人把类继承和原型继承弄混
后来出现了 Object.create 这个方法来实现原型继承
刚才的那个例子改成下面这样 :

  1. var proto = {
  2. sentence : 3,
  3. provation : 2
  4. };
  5. var firstPrisoner = Object.create(proto);
  6. firstPrisoner.name = "wang";
  7. firstPrisoner.id = "12A";
  8. var secondPrisoner = Object.create(proto);
  9. secondPrisoner.name = "li";
  10. secondPrisoner.id = "12B";

这样也就避免了设置 prototype 引发的一些问题, 而且使用 Object.cteate 给人一种基于某个对象创建的感觉, 应该更符合 JavaScript 原型继承的思想

当前 ECMAScript 引入了 class 关键字, 所以现在完全可以以类继承的方式进行程序设计

工厂模式与 Object.create 的结合

上面那段代码虽然避免了构造函数的一些问题, 但是有一些重复的代码而显的不简洁

因此我们可以采用工厂模式来解决这个问题 :

  1. var proto = {
  2. sentence : 3,
  3. provation : 2
  4. };
  5. var makePrisoner = function(name, id) {
  6. var prisoner = Object.create(proto);
  7. prisoner.name = name;
  8. prisoner.id = id;
  9. };
  10. var firstPrisoner = makePrisoner("wang", "12A");
  11. var secondPrisoner = makePrisoner("li", "12B");

工厂函数可以以 make<Object-name> 的形式命名

Object.create 的向前兼容

Object.create 的概念提出的比较晚, 因此对于一些老的浏览器并不兼容

因此, 我们可以这样解决 :

  1. var objectCreate = function( proto ) {
  2. if ( !proto ) return {};
  3. function obj() {};
  4. obj.prototype = proto;
  5. return new obj;
  6. };
  7. Object.create = Object.create || objectCreate;
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注