繁体   English   中英

克罗克福德的“新”方法

[英]Crockford “new” method

希望有人可以帮我打破Crockford JS Good Parts的一小段代码:

Function.method('new', function ( ) {
  // Create a new object that inherits from the
  // constructor's prototype.
  var that = Object.create(this.prototype);
  // Invoke the constructor, binding –this- to
  // the new object.
  var other = this.apply(that, arguments);
  // If its return value isn't an object,
  // substitute the new object.
  return (typeof other === 'object' && other) || that;
});

我不理解的部分是他使用apply调用模式创建一个对象:

var other = this.apply(that, arguments);

如何执行函数将创建新对象?

如果该功能将是:

var f = function (name) {
   this.name = "name";
};

怎么称呼:

var myF = f.new("my name");

创造对象?

首先,注意Function.method不是内置的JS方法 这是Crockford编造的东西:

Function.prototype.method = function (name, func) {
  this.prototype[name] = func;
  return this;
};

因此, Function.method方法调用基本上是这样做的:

Function.prototype.new = function() {
  var that = Object.create(this.prototype);
  var other = this.apply(that, arguments);
  return (typeof other === 'object' && other) || that;
});

然后当你使用它时

f.new("my name");

它这样做:

  1. 首先,它创建一个继承自f.prototype (instance)的对象。
  2. 然后,它调用f将该实例作为this值传递。
    • 在这种情况下,这会将name属性设置为实例。
    • 此步骤不会创建任何新实例,该实例是在步骤1中创建的。
  3. 如果对f的调用返回了某个对象,则返回该对象。
    否则,返回在步骤1中创建的实例。

用描述性名称重写

Crockford的命名有点模糊,所以这里有相同的功能:

Function.prototype.new = function ( ) {
  var theRealConstructor = this;
  var freshObj = Object.create(theRealConstructor.prototype);

  var freshObj_after_theRealConstructor = 
         theRealConstructor.apply(freshObj, arguments);

  if(typeof freshObj_after_theRealConstructor === 'object'){
     return freshObj_after_theRealConstructor;
  } else {            
     return freshObj; 
  }
};

它希望比更清楚thisother ,和that


详细说明和示例

// this is a Waffle constructor
function Waffle(topping,ingredients){
  this.toppings = topping;
  this.ingredients = ['batter','eggs','sugar'].concat(ingredients);
}

// make the .new method available to all functions
// including our waffle constructor, `Waffle`
Function.prototype.new = function(){

  // inside `Waffle.new`, the `this` will be 
  // `Waffle`, the actual constructor that we want to use
  var theRealConstructor = this;

  // now we create a new object, a fresh waffle,
  // that inherits from the prototype of `Waffle`
  var freshObj = Object.create(theRealConstructor.prototype);

  // and call `Waffle` with it's `this` set to 
  // our fresh waffle; that's what we want the ingredients added to
  var freshObj_after_theRealConstructor = 
         theRealConstructor.apply(freshObj, arguments);

  // If we managed to make an object, return it!
  if(typeof freshObj_after_theRealConstructor === 'object'){
     return freshObj_after_theRealConstructor;

  // otherwise, just return the pre-constructor fresh waffle 
  } else {            
     return freshObj; 
  }
};

// And to try it out 
var myBreakfast = Waffle.new('syrup',['blueberries','chocolate']);

// and `myBreakfast` would look look like  ↓↓
// {
//   toppings: "syrup", 
//   ingredients:[
//     "batter", 
//     "eggs", 
//     "sugar", 
//     "blueberries", 
//     "chocolate"
//   ]
// }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM