2012-01-15 30 views
0

這是適用於使用應用和調用與構造函數(提供一個空對象)的適當方式?應用/與構造函數調用

var findCats = RegExp.apply({}, ["cats?", "ig"]); 
var findDogs = RegExp.call({}, "dogs?", "ig"); 

我只是有一個鬼鬼祟祟的懷疑在幕後:

function Foo(a,b,c) { this.a = a; this.b = b; this.c = c; } 
var foo = Foo.call({}, "a", "b", "c"); 

是不會做的相當同樣的事情

var foo = new Foo("a", "b", "c"); 

回答

0

此:

var foo = new Foo("a", "b", "c"); 

幾乎是一樣的s:

var foo = (function() { var obj = {}; Foo.call(obj, "a", "b", "c"); return obj; })(); 

但不完全是因爲一些簿記。

+1

的'OBJ =的Object.create(Foo.prototype)'一步真的,真的很重要 – Raynos 2012-01-15 19:23:52

+0

@Raynos是的,這就是我所說的「簿記」筆記:-)我明白(也許不是)這個問題的重點是關於這些任務右側的基本*值*,所以這就是我試圖解決的問題。 – Pointy 2012-01-15 19:52:25

1

你說得對。直接使用調用/應用與構造函數是不一樣的。

您可以修改的構造雖然正在使用的對象的測試是構造的一個實例...

function Foo(a,b,c) { 
    if(!(this instanceof Foo)) 
     return new Foo(a,b,c) 
    this.a = a; this.b = b; this.c = c; 
} 

var findCats = Foo.apply({}, ["a", "b", "c"]); 
從構造方法中

所以,如果thisinstanceof Foo,它調用new Foo(a,b,c)傳遞參數。

如果要傳遞未知數量的參數,這當然不起作用。

DEMO:http://jsfiddle.net/7ss3m/


不同的選項將是對剛剛從Foo返回新對象的構造一個無參數的行爲,然後執行.apply()作爲一個單獨的呼叫。

function Foo(a,b,c) { 
    if(arguments.length === 0) 
     return this; 
    this.a = a; this.b = b; this.c = c; 
} 

var findCats = new Foo; // get the empty Foo object 

Foo.apply(findCats, ["a", "b", "c"]); // apply the args separately 

DEMO:http://jsfiddle.net/7ss3m/1/

+0

instanceof檢查只是代碼膨脹。應該用'new'調用構造函數@ – Raynos 2012-01-15 19:23:14

+0

@Raynos:你有什麼反對膨脹?沒有膨脹,jQuery將不可能! ;) – 2012-01-15 19:30:46

+1

...我們不需要那種無稽之談,要麼讓你的API使用'new'或不使用new。這兩個都是糟糕的API設計(是的,jQuery有糟糕的API設計) – Raynos 2012-01-15 19:34:38

1

這不是一回事,默認構造函數通常在他們身上有很多的魔法所以即使傳遞null那裏工作。

而是使用自定義構造函數:

var foo = Foo.call({}, "a", "b", "c");

Foo被稱爲正常的功能,因此fooundefined因爲Foo時稱爲普通函數不返回任何東西。即使您在那裏添加了return thisfoo也不會有Foo.prototype的原始鏈接。

0

var foo = new Foo("a", "b", "c");

可以寫成

var foo = new(Foo, "a", "b", "c");

這意味着你將實現new作爲

function new(constructor) { 
    var o = Object.create(constructor.prototype); 
    var ret = o.constructor.call(o, [].slice.call(arguments, 1)); 
    if (typeof ret !== "number" && 
     typeof ret !== "string" && 
     typeof ret !== "boolean" && 
     ret !== undefined && 
     ret !== null 
    ) { 
     return ret; 
    } 
    return o; 
} 
+0

你不是在暗示函數實際上被命名爲'new',對吧? – 2012-01-15 19:34:36

+0

不,我認爲'new'實際上會在舊瀏覽器中引發錯誤作爲函數名稱 – Raynos 2012-01-15 19:35:08

+1

不僅僅是舊版瀏覽器。這是一個保留字。你可能在想着財產名稱。保留字在那裏有效,但較舊的瀏覽器會中斷。 – 2012-01-15 19:37:14