pr1*_*001 59 javascript oop function
让我说我有var a = function() { return 1; }
.有可能改变a
以便a()
返回2
吗?也许通过编辑a
对象的属性,因为每个函数都是一个对象?
更新:哇,谢谢所有回复.但是,我担心我不想简单地重新分配变量,而是实际编辑现有函数.我正在思考如何在Scala中组合部分函数来创建新函数PartialFunction
.我有兴趣在Javascript中编写类似的东西,并且认为现有的函数可能可以更新,而不是创建一个全新的Function
对象.
jve*_*ema 41
你可以用javascript做各种有趣的事情,包括重新定义功能:
var a = function(){ return 1; }
alert(a()); //1
// keep a reference
var old = a;
// redefine
a = function(){
// call the original function with any arguments specified, storing the result
var originalResult = old.apply(old, arguments);
// add one
return originalResult + 1;
};
alert(a()); //2
Run Code Online (Sandbox Code Playgroud)
瞧.
编辑:更新以在更疯狂的场景中显示:
var test = new String("123");
console.log(test.toString()); // logs 123
console.log(test.substring(0)); // logs 123
String.prototype.substring = function(){ return "hahanope"; }
console.log(test.substring(0)); // logs hahanope
Run Code Online (Sandbox Code Playgroud)
你可以在这里看到,即使首先定义了"test",然后我们重新定义了substring(),但更改仍然适用.
旁注:如果你这样做,你真的应该重新考虑你的架构......当他/她正在寻找一个应该返回1的函数定义时,你将会混淆一些可怜的开发人员5年后的废话,但似乎总是返回2 ....
hmu*_*ndt 40
我使用这样的东西来修改我无法访问其声明的现有函数:
// declare function foo
var foo = function (a) { alert(a); };
// modify function foo
foo = new Function (
"a",
foo.toSource()
.replace("alert(a)", "alert('function modified - ' + a)")
.replace(/^function[^{]+{/i,"") // remove everything up to and including the first curly bracket
.replace(/}[^}]*$/i, "") // remove last curly bracket and everything after<br>
);
Run Code Online (Sandbox Code Playgroud)
您可以使用toString()来获取包含函数声明的字符串,而不是toSource().有些调用replace()来准备字符串以便与Function Constructor一起使用并修改函数的源代码.
Sam*_*ler 22
var a = function() { return 1; }
alert(a()) // 1
a = function() { return 2; }
alert(a()) // 2
Run Code Online (Sandbox Code Playgroud)
从技术上讲,你丢失了一个函数定义并将其替换为另一个函数定义.
jps*_*ons 15
怎么样,无需重新定义功能:
var a = function() { return arguments.callee.value || 1; };
alert(a()); // => 1
a.value = 2;
alert(a()); // => 2
Run Code Online (Sandbox Code Playgroud)
rpl*_*iko 11
我坚持使用jvenema的解决方案,我不喜欢全局变量"old".将旧函数保留在新函数中似乎更好:
function a() { return 1; }
// redefine
a = (function(){
var _a = a;
return function() {
// You may reuse the original function ...
// Typical case: Conditionally use old/new behaviour
var originalResult = _a.apply(this, arguments);
// ... and modify the logic in any way
return originalResult + 1;
}
})();
a() // --> gives 2
Run Code Online (Sandbox Code Playgroud)
所有可行的解决方案都坚持“函数包装方法”。 其中最可靠的,似乎是rplantiko之一。
这样的函数包装很容易被抽象掉。概念/模式本身可能被称为“方法修改”。它的实现绝对属于Function.prototype
. 这将是很好的标准原型方法修饰符等支持1天before
,after
,around
,afterThrowing
和afterFinally
。
至于前面提到的rplantiko 的例子......
function a () { return 1; }
// redefine
a = (function () {
var _a = a;
return function () {
// You may reuse the original function ...
// Typical case: Conditionally use old/new behaviour
var originalResult = _a.apply(this, arguments);
// ... and modify the logic in any way
return originalResult + 1;
};
})();
console.log('a() ...', a()); // --> gives 2
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { min-height: 100%!important; top: 0; }
Run Code Online (Sandbox Code Playgroud)
...并利用around
,代码将转换为 ...
function a () { return 1; }
console.log('original a ...', a);
console.log('a() ...', a()); // 1
a = a.around(function (proceed, handler, args) {
return (proceed() + 1);
});
console.log('\nmodified a ...', a);
console.log('a() ...', a()); // 2
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { min-height: 100%!important; top: 0; }
Run Code Online (Sandbox Code Playgroud)
<script>
(function(d){function f(a){return typeof a==e&&typeof a.call==e&&typeof a.apply==e}function g(a,b){b=null!=b&&b||null;var c=this;return f(a)&&f(c)&&function(){return a.call(b||null!=this&&this||null,c,a,arguments)}||c}var e=typeof d;Object.defineProperty(d.prototype,"around",{configurable:!0,writable:!0,value:g});Object.defineProperty(d,"around",{configurable:!0,writable:!0,value:function(a,b,c){return g.call(a,b,c)}})})(Function);
</script>
Run Code Online (Sandbox Code Playgroud)