76

私が持っているとしましょうvar a = function() { return 1; }aa()返すように変更することは可能2ですか? すべての関数はオブジェクトであるため、おそらくオブジェクトのプロパティを編集することによってaですか?

更新:うわー、すべての応答に感謝します。ただし、単純に変数を再割り当てするのではなく、実際に既存の関数を編集しようとしていたのではないでしょうか。私は、Scala で部分関数PartialFunctionを組み合わせて新しい を作成する方法について考えています。FunctionJavascript で似たようなものを書くことに興味があり、まったく新しいオブジェクトを作成するのではなく、既存の関数を更新できるのではないかと考えていました。

4

13 に答える 13

50

関数の再定義を含め、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を返すようです....

于 2010-01-25T23:45:59.100 に答える
42

次のようなものを使用して、宣言にアクセスできない既存の関数を変更しました。

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

toSource() の代わりにtoString()を使用して、関数の宣言を含む文字列を取得できます。関数コンストラクターで使用する文字列を準備し、関数のソースを変更するための replace() の呼び出し。

于 2010-01-26T23:18:17.183 に答える
21
let a = function() { return 1; }
console.log(a()) // 1

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

技術的には、1 つの関数定義を失い、別の関数定義に置き換えています。

于 2010-01-25T23:37:33.073 に答える
16

関数を再定義する必要なしに、これはどうですか:

var a = function() { return arguments.callee.value || 1; };
alert(a()); // => 1
a.value = 2;
alert(a()); // => 2
于 2010-01-26T00:09:51.120 に答える
6

すべての実行可能なソリューションは、「関数ラッピング アプローチ」に固執します。 それらの中で最も信頼できるのは rplantiko のもののようです

このような関数ラッピングは簡単に抽象化できます。コンセプト・パターンそのものを「メソッド改変」と呼んでもいいかもしれません。その実装は間違いなく に属しFunction.prototypeます。beforeafteraroundafterThrowingなどの標準的なプロトタイプ メソッド修飾子がいつの日かサポートされるとよいでしょう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
.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>

于 2014-12-17T19:40:41.163 に答える
1

これは、コントロール タイム ピッカー www.eworldui.netに基づく明確な例です。eworld.ui

JavaScript が外部からアクセスできないTimePickereworld.uiがあると、それらのコントロールに関連する js が見つかりません。では、onchange イベントを timepicker に追加するにはどうすればよいでしょうか。

コントロールが提供するすべてのオプションの間にあるjsときに呼び出される関数があります。Selectこの関数は次のとおりです。 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);
}

My Function を関数に追加したので、時間を選択したときに onchange イベントをシミュレートできるようになりました。

RaiseChange(...) は何でもかまいません。

于 2013-10-22T15:42:41.197 に答える
0

JavaScript をデバッグしていて、コードの変更がページにどのように影響するかを確認したい場合は、この Firefox 拡張機能を使用して JavaScript を表示/変更できます。

JS Firefox 拡張機能を実行します: https://addons.mozilla.org/en-US/firefox/addon/1729

于 2010-01-25T23:43:08.963 に答える
-1
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
于 2021-01-18T18:36:49.477 に答える
-2

絶対。それに新しい機能を割り当てるだけです。

于 2010-01-25T23:38:02.470 に答える
-2

後でもう一度定義することはできませんか?変更が必要な場合は、次のように再定義してみてください。

a = function() { return 2; }
于 2010-01-25T23:39:13.653 に答える