2016-02-19 86 views
2

因此,我構建了一些可執行簡單類型檢查的可鏈接函數。目前,我打電話給我的功能是這樣的:API:在JavaScript中構造不帶括號的可鏈接函數

Proceed().if('someString').is.a('string'); 

但我真正想要是我的API看起來像這樣:

proceed.if('someString').is.a('string'); 

注意,第二個代碼示例中,第一個函數調用中缺少開始和結束括號。

正如你可以從下面的代碼中看到的,我已經想通了如何讓isa工作,但我似乎無法找到一種方法,以消除來自Proceed()功能括號。

下面是代碼示例,工程

function Proceed() { 
    if (!(this instanceof Proceed)) { 
     return new Proceed(); 
    } 
    this.target = ""; 
} 

Proceed.prototype.if = function (target) { 
    this.target = target; 
    return this; 
} 

Proceed.prototype.a = function (type) { 
    console.log(this.target + ' === ' +type, typeof this.target === type); 
}; 

Object.defineProperty(Proceed.prototype, 'is', { 
     get: function() { 
      return this; 
     } 
    }); 


Proceed().if('someString').is.a('string'); // true 
Proceed().if('someString').is.a('function'); // false 


// Everything Above this line Works! 

而現在,我試圖從Proceed()刪除括號看起來是這樣的:

Object.defineProperty(Proceed.prototype, 'proceed', { 
    set: function(){}, 
    get: function(){ 
    return Proceed(this); 
    }, 
    configurable: true 
}); 

proceed.if('someString').is.a('string'); // ReferenceError 
proceed.if('someString').is.a('function'); // ReferenceError 

我從這裏得到的錯誤是這個:

Uncaught ReferenceError: proceed is not defined

如果我用Object.prototype替換Proceed.prototype然後我可以使它工作,但這意味着我已經擴展了一個本地對象,這可能是有問題的。

因此,有誰知道一種方法,我可以把它關閉而不危險地擴展本地對象?我在這裏做錯了什麼?

Here is a jsFiddle with the above code samples

任何幫助表示讚賞。

UPDATE#1此代碼被設計爲節點模塊,因此不會有任何訪問瀏覽器的window對象。

+0

不要以爲你可以不擴展對象或窗口。我用窗口而不是繼續測試:https://jsfiddle.net/Lw29zyf1/4/ –

回答

2

您需要啓動一個實例值的變量:

var proceed = new Proceed(); 

,並使其可鏈接的,你應該從你的方法返回新實例,而不是突變的「靜態」 proceed對象:

function Proceed(target) { 
    this.target = arguments.length ? target : ""; 
} 

Proceed.prototype.if = function (target) { 
    return new Proceed(target); 
} 

或者一般情況下,您需要使proceed.if工廠返回Proceed實例,而不管proceed已經是一個還是一個普通對象。

(jsfiddle demo)

+0

感謝您花時間看看這個!乍一看,它似乎可行,但它也有不會在每次調用中返回新實例的副作用。每次我調用proceed.if()...''我需要一個新的'Proceed'實例,但是在你的演示中,我發現每個後續調用都保留了前一個調用的值,就好像'proceed'只是一個變量。我用演示更新了演示。請注意底部的console.log()語句:https://jsfiddle.net/Lw29zyf1/6/。再次感謝,我非常感謝你的幫助! – radiovisual

+0

哎呀,[小提琴](https://jsfiddle.net/Lw29zyf1/5/)有兩個'if'方法,你的舊實現覆蓋了我的答案中的工作。固定。 – Bergi

+0

美麗!這對我行得通。非常感謝你!你剛在我的實驗庫上幫我[關閉這張票](https://github.com/radiovisual/detonate/issues/1)。非常感激。 – radiovisual

0

變化:

Object.defineProperty(Proceed.prototype, 'proceed', { 

Object.defineProperty(window, 'proceed', { 

更新小提琴:https://jsfiddle.net/Lw29zyf1/4/

所以你必須在窗口範圍 「進行」 變量。

+0

是的,這確實有助於完成工作!但是,我需要這樣做還可以在獨立的節點環境中工作,我不能訪問窗口對象。我會更新我的問題,讓讀者知道這段代碼應該能夠在節點以及瀏覽器中運行。謝謝! – radiovisual

+0

但是對於那些希望在瀏覽器環境中做類似工作的人來說,這是一個很好的答案。謝謝! – radiovisual

0

請看看下面的代碼是任何幫助

var proto = Object.create(null); 
proto.a = function(type) { 
console.log(this.target + ' === ' + type, typeof this.target === type); 

}; 

Object.defineProperty(proto, 'is', { 
    get: function() { 
     return this; 
    } 
}); 

proto.if = function(target) { 
this.target = target; 
return this; 

}; 


var proceed = Object.create(proto); 

proceed.if('someString').is.a('string'); 
+0

你能解釋一下爲什麼你使用'Object.create'嗎? – Bergi

+0

因爲它是唯一的方法,我們可以在不使用構造函數的情況下將原型分配給對象。 –

+0

這樣做的作用是它*創建所需的API,但您的示例是創建一個對象,而不是使用函數,並且問題集中在函數上。但是,如果我使用的是對象,這確實完成了工作,所以我很感謝您的意見! – radiovisual