优化JavaScript构造函数

May 6, 2015

445

之前写过一篇文章《关于underscore.js源码的一些理解与笔记》,里面涉及到的自调用构造函数,代码如下:

var _ = function(obj) {
  if (obj instanceof _) return obj;
  if (!(this instanceof _)) return new _(obj);
  this._wrapped = obj;
};

这段代码不管以函数的方式或者是以构造函数的方式调用,都会返回一个继承 _.prototype 的对象。但这种模式有一个缺点,使用函数调用时,需要额外的函数调用,代价比较高。可以通过以下代码来验证:

var _ = function(obj) {
  console.log('create_');
  if (obj instanceof _) return obj;
  if (!(this instanceof _)) {
    console.log('new_');
    return new _(obj);
  }
  this._wrapped = obj;
  console.log('wrapped_');
},
a = _(), //log: create_ new_ create_ wrapped_
b = new _(); //log: create_ wrapped_

那么,我们该如何来优化这种方式呢?

利用ES5的Object.create函数来创建对象。Object.create() 方法创建一个拥有指定原型和若干个指定属性的对象。修改后的代码如下:

var _ = function(obj) {
  if (obj instanceof _) return obj;
  var self = this instanceof _ ? this : Object.create(_.prototype);
  self._wrapped = obj;
};

采用如下代码做验证:

var _ = function(obj) {
  console.log('create_');
  if (obj instanceof _) return obj;
  var self = this instanceof _ ? this : Object.create(_.prototype);
  self._wrapped = obj;
  console.log('wrapped_');
},
a = _(), //log: create_ wrapped_
b = new _(); //log: create_ wrapped_

这时候,不管采不采用new实例化对象,都只会调用一次,同时将构造函数的参数解耦出来,可以适用于可变参数函数。但Object.create只有在ES5环境中才有效,在旧环境需要创建一个局部的构造函数并使用new初始化的函数来替代Object.create。

简单起见,实现一个单参数版本,代码如下:

if (typeof Object.create === 'undefined') {
 Object.create = (function(prototype) {
   function C(){}
   return function(prototype) {
     C.prototype = prototype;
     return new C();
   }
 }());
}

JavaScript 」相关文章

Wen's Blog

文章归档 » 文章标签 » 博主:吴文伟,Web开发爱好者,专注于前端开发,该博客用于记录和分享平时遇到的一些问题以及知识。

订阅

联系方式

链接