2015-06-30 165 views
9

我需要在JavaScript中調用一個函數。對於這一點,我在「拯救」在一個臨時變量的功能,更新了新的功能塊的目標,要求目標,然後恢復舊的功能:覆蓋和恢復功能

var myObject = { 
 
    myIntProp: 1, 
 
    myFunc: function(value) { 
 
    alert(value + 1); 
 
    } 
 
}; 
 
myObject.myFunc(2); 
 

 
var tmp = myObject.myFunc; 
 
myObject.myFunc = function(value) { 
 
    alert(value - 1); 
 
}; 
 
myObject.myFunc(2); 
 

 
myObject.myFunc = tmp; 
 
myObject.myFunc(2);

該作品如預期的那樣:函數被覆蓋,然後成功恢復。我的想法是這個代碼轉移到一個輔助功能,方便地使用它需要的時候:

function FunctionSwapper(target, newFunction) { 
 
    var old = target; 
 
    target = newFunction; 
 
    this.Restore = function() { 
 
    target = old; 
 
    } 
 
}; 
 

 
var myObject = { 
 
    myIntProp: 1, 
 
    myFunc: function(value) { 
 
    alert(value + 1); 
 
    } 
 
}; 
 
myObject.myFunc(2); 
 

 
var swapp = new FunctionSwapper(myObject.myFunc, function(value) { 
 
    alert(value - 1); 
 
}); 
 
myObject.myFunc(2); 
 

 
swapp.Restore(); 
 
myObject.myFunc(2);

此代碼然而,不保存當前的狀態也不是更換有針對性的功能。我在這裏錯過了什麼?是不是一個函數總是作爲參考傳遞?這兩個代碼片段之間的主要區別是什麼?

JSFiddle可用,但準備8個alert小號......)

編輯:資深用戶已經指出,第二種方法並沒有真正從第一個不同,它可能不值得麻煩創建附加類;雖然我理解並與他們的論點同意,我看到了第二個方法有兩個優點(既適用於我特別,真實世界的情況下):

  1. 更容易/快寫swapp.Restore();myNameSpace.level2.level3.level4.level5 = swap;工作時與具有子元素的幾個層次和對象,
  2. 它抽象的操作,並提供開發團隊(另外,記錄或類型打樣可以在類內完成)之間的一致的使用。

回答

5

這是因爲target是不是一個真正的參考,它是引用target函數的值。

然而,當您重新分配的目標,你不要修改舉行值(參考函數),但你直接修改的值,這意味着你不能做這種方式。

相反,你可以通過按住功能來取代(這隻會與對象的工作,因爲你以後需要訪問它)的對象。

這裏是我想出了

function FunctionSwapper(target, name, newFunction) { 
    var old = target[name]; 
    target[name] = newFunction; 
    this.Restore = function() { 
    target[name] = old; 
    } 
}; 

var myObject = { 
    myIntProp: 1, 
    myFunc: function(value) { 
    alert(value + 1); 
    } 
}; 
myObject.myFunc(2); 

var swapp = new FunctionSwapper(myObject, 'myFunc', function(value) { 
    alert(value - 1); 
}); 
myObject.myFunc(2); 

swapp.Restore(); 
myObject.myFunc(2); 
+0

啊,你打我的15秒顯然與幾乎相同的答案! – mGuv

3

FunctionSwapper正在恢復其自身功能的副本,但它有沒有myObject連接(你不把它傳遞給myObject參考)。

這會工作:

function FunctionSwapper(object,name,newFunction) { 
    var old = object[name]; 
    object[name] = newFunction; 
    this.Restore = function() { 
    object[name] = old; 
    } 
}; 

...

var swapp = new FunctionSwapper(myObject, "myFunc", function(value) { 
    alert(value - 1); 
}); 
3

我相信通過傳遞myObject.myFunc,你實際上脫離myObject參考,所以它實際上沒有更新myFunc通話myObject,它更新本地範圍FunctionSwapper的副本。

比較它這個,它進行操作的對象本身:

function FunctionSwapper(obj, funcName, newFunction) { 
    var old = obj[funcName]; 
    obj[funcName] = newFunction; 
    this.Restore = function() { 
     obj[funcName] = old; 
    } 
}; 

var myObject = { 
    myIntProp: 1, 
    myFunc: function(value) { 
    alert(value + 1); 
    } 
}; 
myObject.myFunc(2); 

var swapp = new FunctionSwapper(myObject, "myFunc", function(value) { 
    alert(value - 1); 
}); 
myObject.myFunc(2); 

swapp.Restore(); 
myObject.myFunc(2);