2013-05-07 20 views
2

我想只替换JavaScript对象的“函子”函数。下面的代码演示了此问题:只替换JavaScript中的“函子”

// PART 1: Declaration 
function obj() { 
    return obj.a + " " + obj.b; 
}; 
obj.a = "a"; 
obj.b = "b"; 
confirm(obj()); // output: "a b"; 

// PART 2: Modification 
// now replace only functor 
// (not working this way as it replaces the whole object) 
obj = function() { 
    return obj.b + " " + obj.a; 
}; 
confirm(obj()); // expected output: "b a"; 

我需要这个,因为我没有获得第1部和需要修改的对象的功能...

有没有办法在JavaScript中执行此?

复制(例如用一个for循环)不工作,因为它不会复制所有的隐藏属性...

UPDATE:修改后的代码,它不是不确定的......

UPDATE2:这似乎在这个例子中工作:(需要jQuery的)

obj = $.extend(function() { return obj.b + " " + obj.a; }, obj); 
confirm(obj()); // output: "b a"; 

(但是它并没有解决我的问题...)

+0

对于所有浏览器,它是未定义的undefined – 2013-05-07 08:06:39

+1

没有JavaScript对象,只是一个函数。 'a'和'b'是函数的属性,没有包含它们的对象。 – Barmar 2013-05-07 08:12:25

+0

你可以发布你试过的“for-loop”代码吗? – Dogbert 2013-05-07 08:14:02

回答

0

您需要反转您的功能/对象。这是一个对象,并在其中放置一个函数。这将意味着,为了调用函数,你需要这样指定对象:

obj = { 
    functor : function() { 
    return this.a + " " + this.b; 
    } 
}; 
obj.a = "a"; 
obj.b = "b"; 
confirm (obj.functor()); // output: "a b"; 

// PART 2: Modification 
// now replace only functor 
obj.functor = function() { 
    return this.b + " " + this.a; 
}; 
confirm (obj.functor()); // expected output: "b a"; 
+0

这不会工作,因为对象obj的客户端将调用obj(),我不能改变那个... – 2013-05-07 08:21:04

0

我想包像这样(将此代码粘贴到浏览器的控制台):

// PART 1 - exactly as provided 

function obj() { 
    return obj.a + " " + obj.b; 
}; 
obj.a = "a"; 
obj.b = "b"; 
console.log(obj()); // output: "a b"; 

// PART 2 - object is used in different context 

var API = { 
    setObj: function(obj) { 
     this._obj = obj; 
    }, 
    useObj: function() { 
     console.log("API: " + this._obj()); 
    } 
} 

API.setObj(obj); 
API.useObj(); 

// PART 3 - wrapping obj, changing it's default behavior 

objWrapper = function(obj) { 

    var wrappedObj = function() { 
     return wrappedObj.b + " " + wrappedObj.a; 
    } 

    var i; 
    for(i in obj) { 
     if(obj.hasOwnProperty(i)) { 
      wrappedObj[i] = obj[i]; 
     } 
    } 

    return wrappedObj; 
} 
obj = objWrapper(obj); 
console.log(obj()); // expected output: "b a"; 
console.log(obj.a); 
console.log(obj.b); 
obj.c = "c"; 
console.log(obj.c); 

// PART 4 - checking different context 

API.setObj(obj); 
API.useObj(); 

这是只有这样你才能使它工作。你将不得不更新对这个函数的每一个引用,所以如果你不能模拟API.setObj(obj);那么你不能使它工作。你不能重新定义一个函数的主体。也许将来他们会添加它,因为它可能确实有帮助,它将使JS更具功能性的编程语言。

我更换confirm对话为console.log,因为它是恼人!;)

希望这将有助于!

+0

我不认为这将工作,因为我需要外部对象上的所有属性(如其他类期望的他们在那里......) – 2013-05-07 08:25:21

+0

你正将'obj'传递给objWrapper。这样你不会失去对这个对象的引用。您可以轻松玩这个代码,甚至可以在需要时返回此引用的属性! – Karol 2013-05-07 08:27:15

+0

但是obj.a最后没有定义,对吧? – 2013-05-07 08:30:48

1

你需要有一个对象和一个相互引用的函数,然后你只需要改变它的函数部分。

var obj = function() { 
    var x = function() {return x.f();}; 
    x.f = function() { return x.a + " " + x.b; }; 
    return x; 
}(); 

obj.a = "a"; 
obj.b = "b"; 

alert(obj()); 

要更改功能,只需更改obj.f:

obj.f = function() { 
    return obj.b + " " + obj.a; //swap the order. 
}; 

alert(obj()); 

编辑:错过了,你说你没有进入第一部分的部分,所以这个解决方案荣获” t为你工作,但是为了帮助别人,这里留下了它,并且因为它允许你直接使用obj()。