簡體   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