声明 Javascript 函数后可以更改它吗?

发布于 2024-08-18 18:33:07 字数 576 浏览 3 评论 0原文

假设我有 var a = function() { return 1; }。是否可以更改 a 以使 a() 返回 2 ?也许可以通过编辑 a 对象的属性,因为每个函数是一个对象

更新:哇,感谢您的所有回复。但是,恐怕我并不是想简单地重新分配变量,而是实际编辑现有函数。我正在思考如何组合 部分函数 在 Scala 中创建一个新的 PartialFunction。我有兴趣用 Javascript 编写类似的东西,并且认为现有的函数也许可以更新,而不是创建一个全新的 Function 对象。

Let's say I have var a = function() { return 1; }. Is it possible to alter a so that a() returns 2? Perhaps by editing a property of the a object, since every function is an object?

Update: Wow, thanks for all the responses. However, I'm afraid I wasn't looking to simply reassign a variable but actually edit an existing function. I am thinking along the lines of how you can combine partial functions in Scala to create a new PartialFunction. I am interested in writing something similar in Javascript and was thinking that the existing function could perhaps be updated, rather than creating an entirely new Function object.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

╰つ倒转 2024-08-25 18:33:08
let a = function() { return 1; }
console.log(a()) // 1

a = function() { return 2; }
console.log(a()) // 2

从技术上讲,您正在丢失一个函数定义并将其替换为另一个函数定义。

let a = function() { return 1; }
console.log(a()) // 1

a = function() { return 2; }
console.log(a()) // 2

technically, you're losing one function definition and replacing it with another.

缺⑴份安定 2024-08-25 18:33:08

怎么样,不必重新定义函数:

var a = function() { return arguments.callee.value || 1; };
alert(a()); // => 1
a.value = 2;
alert(a()); // => 2

How about this, without having to redefine the function:

var a = function() { return arguments.callee.value || 1; };
alert(a()); // => 1
a.value = 2;
alert(a()); // => 2
拥抱影子 2024-08-25 18:33:08

我坚持使用 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

I am sticking to jvenema's solution, in which I don't like the global variable "old". It seems better to keep the old function inside of the new one:

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
十雾 2024-08-25 18:33:08

所有可行的解决方案都坚持“功能包装方法”。
其中最可靠的似乎是 rplantiko

这种函数包装很容易被抽象掉。概念/模式本身可以称为“方法修改”。它的实现肯定属于Function.prototype。很高兴得到支持
有一天,通过标准原型方法修饰符,例如 before之后周围afterThrowingafterFinally.

至于前面提到的 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
.as-console-wrapper { min-height: 100%!important; top: 0; }

...并利用 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
.as-console-wrapper { min-height: 100%!important; top: 0; }
<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>

All feasible solutions stick to a "function wrapping approach".
The most reliable amongst them seems to be the one of rplantiko.

Such function wrapping easily can be abstracted away. The concept / pattern itself might be called "Method Modification". Its implementation definitely belongs to Function.prototype. It would be nice to be backed
one day by standard prototypal method modifiers like before, after, around, afterThrowing and afterFinally.

As for the aforementioned example by 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
.as-console-wrapper { min-height: 100%!important; top: 0; }

... and making use of around, the code would transform to ...

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
.as-console-wrapper { min-height: 100%!important; top: 0; }
<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>

凶凌 2024-08-25 18:33:08

这是一个基于控件时间选择器eworld.ui清晰示例
www.eworldui.net

有一个 TimePicker eworld.ui,其中 JavaScript 无法从外部访问,您无法找到与这些控件相关的任何 js。那么如何向时间选择器添加 onchange 事件呢?

当您在控件提供的所有选项之间选择时间时,会调用一个 js 函数。该函数是:TimePicker_Up_SelectTime

首先,您必须复制该函数内的代码。

评估...quikwatch...TimePicker_Up_SelectTime.toString()

function TimePicker_Up_SelectTime(tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
    document.getElementById(tbName).value = selTime;
    if(lblName != '')
        document.getElementById(lblName).innerHTML = selTime;
    document.getElementById(divName).style.visibility = 'hidden';
    if(enableHide)
        TimePicker_Up_ShowHideDDL('visible');
    if(customFunc != "")
        eval(customFunc + "('" + selTime + "', '" + tbName + "');");
    eval(postbackFunc + "();");
}

现在

使用您在重新分配相同源代码之前保存的代码,但添加您想要的任何内容..

TimePicker_Up_SelectTime = function (tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
    document.getElementById(tbName).value = selTime;
    if (lblName != '')
        document.getElementById(lblName).innerHTML = selTime;
    document.getElementById(divName).style.visibility = 'hidden';
    if (enableHide)
        TimePicker_Up_ShowHideDDL('visible');
    if (customFunc != "")
        eval(customFunc + "('" + selTime + "', '" + tbName + "');");
    eval(postbackFunc + "();");

    >>>>>>>  My function  >>>>>   RaiseChange(tbName);
}

我已将“我的函数”添加到该函数中所以现在我可以在选择时间时模拟 onchange 事件。

RaiseChange(...) 可以是您想要的任何内容。

This is a Clear Example based on a control timepicker eworld.ui
www.eworldui.net

Having a TimePicker eworld.ui where JavaScript is unreachable from outside, you can't find any js related to those controls. So how can you add a onchange event to the timepicker ?

There is a js function called when you Select a time between all the options that the control offer you. This function is: TimePicker_Up_SelectTime

First you have to copy the code inside this function.

Evaluate...quikwatch...TimePicker_Up_SelectTime.toString()

function TimePicker_Up_SelectTime(tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
    document.getElementById(tbName).value = selTime;
    if(lblName != '')
        document.getElementById(lblName).innerHTML = selTime;
    document.getElementById(divName).style.visibility = 'hidden';
    if(enableHide)
        TimePicker_Up_ShowHideDDL('visible');
    if(customFunc != "")
        eval(customFunc + "('" + selTime + "', '" + tbName + "');");
    eval(postbackFunc + "();");
}

Now

Using the code that you have saved before reassign the same source code but add whatever you want..

TimePicker_Up_SelectTime = function (tbName, lblName, divName, selTime, enableHide, postbackFunc, customFunc) {
    document.getElementById(tbName).value = selTime;
    if (lblName != '')
        document.getElementById(lblName).innerHTML = selTime;
    document.getElementById(divName).style.visibility = 'hidden';
    if (enableHide)
        TimePicker_Up_ShowHideDDL('visible');
    if (customFunc != "")
        eval(customFunc + "('" + selTime + "', '" + tbName + "');");
    eval(postbackFunc + "();");

    >>>>>>>  My function  >>>>>   RaiseChange(tbName);
}

I've added My Function to the function so now I can simulate an onchange event when I select a time.

RaiseChange(...) could be whatever you want.

幸福%小乖 2024-08-25 18:33:08

如果您正在调试 javascript 并希望了解代码更改如何影响页面,您可以使用此 Firefox 扩展来查看/更改 javascript:

执行 JS firefox 扩展:
https://addons.mozilla.org/en-US/firefox/addon/第1729章

If you're debugging javascript and want to see how changes to the code affects the page, you can use this Firefox extension to view/alter javascripts:

Execute JS firefox extension:
https://addons.mozilla.org/en-US/firefox/addon/1729

一世旳自豪 2024-08-25 18:33:08
const createFunction = function (defaultRealization) {
  let realization = defaultRealization;

  const youFunction = function (...args) {
    return realization(...args);
  };
  youFunction.alterRealization = function (fn) {
    realization = fn;
  };

  return youFunction;
}

const myFunction = createFunction(function () { return 1; });
console.log(myFunction()); // 1

myFunction.alterRealization(function () { return 2; });
console.log(myFunction()); // 2
const createFunction = function (defaultRealization) {
  let realization = defaultRealization;

  const youFunction = function (...args) {
    return realization(...args);
  };
  youFunction.alterRealization = function (fn) {
    realization = fn;
  };

  return youFunction;
}

const myFunction = createFunction(function () { return 1; });
console.log(myFunction()); // 1

myFunction.alterRealization(function () { return 2; });
console.log(myFunction()); // 2
当梦初醒 2024-08-25 18:33:08

不能稍后再定义吗?当您想要更改时,请尝试将其重新定义为:

a = function() { return 2; }

Can you not just define it again later on? When you want the change try just redefining it as:

a = function() { return 2; }
入画浅相思 2024-08-25 18:33:07

您可以使用 javascript 做各种有趣的事情,包括重新定义函数:

let a = function() { return 1; }
console.log(a()); // 1
    
// keep a reference
let old = a;
   
// redefine
a = function() {
  // call the original function with any arguments specified, storing the result
  const originalResult = old.apply(old, arguments);
  // add one
  return originalResult + 1;
};

console.log(a()); // 2

瞧。

编辑:更新以在更疯狂的场景中显示这一点:

let 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

您可以在这里看到,即使首先定义了“test”,然后我们重新定义了 substring(),更改仍然适用。

旁注:如果你这样做,你真的应该重新考虑你的架构……5年后,当他/她正在查看一个应该返回 1 的函数定义时,你将会把一些可怜的开发人员搞糊涂。 ,但似乎总是返回 2....

You can do all kinds of fun stuff with javascript, including redefining functions:

let a = function() { return 1; }
console.log(a()); // 1
    
// keep a reference
let old = a;
   
// redefine
a = function() {
  // call the original function with any arguments specified, storing the result
  const originalResult = old.apply(old, arguments);
  // add one
  return originalResult + 1;
};

console.log(a()); // 2

Voila.

Edit: Updated to show this in a crazier scenario:

let 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

You can see here that even though "test" is defined first, and we redefine substring() afterwards, the change still applies.

Side note: you really should reconsider your architecture if you're doing this...you're going to confuse the crap out of some poor developer 5 years down the road when s/he's looking at a function definition that's supposed to return 1, but seems to always return 2....

枕梦 2024-08-25 18:33:07

因此,您希望直接就地修改函数的代码,而不仅仅是将不同的函数重新分配给现有变量。

我不想这么说,但就我所能弄清楚的——而且我已经尝试过——来说,这是不可能的。确实,函数是一个对象,因此它具有可以在对象本身上调整和覆盖的方法和属性。不幸的是,函数体不是其中之一。它不属于公共财产。

MDN 上的文档列出了属性和方法函数对象的。它们都没有给我们机会从外部操纵函数体。

这是因为根据规范,函数体被存储位于函数对象的内部 [[Code]] 属性中,无法直接访问。

So you want to modify the code of a function directly, in place, and not just reassign a different function to an existing variable.

I hate to say it, but as far as I have been able to figure it out - and I have tried -, it can't be done. True, a function is an object, and as such it has methods and properties which can be tweaked and overwritten on the object itself. Unfortunately, the function body is not one of them. It is not assigned to a public property.

The documentation on MDN lists the properties and methods of the function object. None of them gives us the opportunity to manipulate the function body from the outside.

That's because according to the spec, the function body is stored in the internal [[Code]] property of the function object, which can't be accessed directly.

╭⌒浅淡时光〆 2024-08-25 18:33:07

我使用类似的方法来修改我无法访问其声明的现有函数:

// 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>
);

您可以使用 toString() 获取包含函数声明的字符串。一些对replace()的调用来准备与函数构造函数一起使用的字符串并修改函数的源代码。

I used something like this to modify an existing function whose declaration was not accessible to me:

// 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>
);

Instead of toSource() you could probably use toString() to get a string containing the function's declaration. Some calls to replace() to prepare the string for use with the Function Constructor and to modify the function's source.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文