web-dev-qa-db-ja.com

Javascript関数を宣言した後に変更できますか?

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

更新:すごい、すべての応答に感謝します。ただし、単に変数を再割り当てするのではなく、実際に既存の関数を編集するのではないかと心配しています。 部分関数 in Scala=を使用して新しいPartialFunctionを作成する方法について考えています。 Javascriptと、まったく新しいFunctionオブジェクトを作成するのではなく、既存の関数を更新できると考えていました。

59
pr1001

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

// 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()の呼び出し。

40
hmundt

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

出来上がり。

編集:クレイジーなシナリオでこれを表示するように更新されました。

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

ここでは、「テスト」が最初に定義され、その後substring()を再定義しても、変更が適用されることがわかります。

サイドノート:これを行う場合は、アーキテクチャを再検討する必要があります... 5年後のある貧しい開発者のがらくたを混乱させるでしょう。 、しかし常に2を返すようです...

39
jvenema
var a = function() { return 1; }
alert(a()) // 1
a = function() { return 2; }
alert(a()) // 2

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

22
Sam Hasler

そのため、既存の変数に別の関数を再割り当てするだけでなく、関数のコードをその場で直接変更したいと考えています。

私はそれを言うことを嫌いますが、私がそれを理解することができた限り-そして私が試みた-それは行うことができません。確かに、関数はオブジェクトなので、オブジェクト自体で調整および上書きできるメソッドとプロパティがあります。残念ながら、関数本体はそれらの1つではありません。パブリックプロパティには割り当てられません。

MDNのドキュメント は、関数オブジェクトのプロパティとメソッドをリストします。それらのどれも、外部から関数本体を操作する機会を与えません。

仕様による であるため、関数本体は関数オブジェクトの内部[[Code]]プロパティに格納され、直接アクセスすることはできません。

18
hashchange

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

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

私は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
11
rplantiko

すべての実行可能なソリューションは、「関数ラッピングアプローチ」に固執します。 それらの中で最も信頼性の高いものは、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;
  };
})();

a(); // --> gives 2

... [around]を使用すると、コードは...

function a () { return 1; }

console.log("a : ", a);
console.log("a() : ", a());


a = a.around(function (proceed, interceptor, args) {
  return (proceed() + 1);
});

console.log("a : ", a);
console.log("a() : ", a());
3
Peter Seliger

他のオブジェクトのような機能を変更できます

var a1 = function(){return 1;}
var b1 = a1;
a1 = function(){
  return b1() + 1;
};
console.log(a1()); // return 2

// OR:
function a2(){return 1;}
var b2 = a2;
a2 = function(){
  return b2() + 1;
};
console.log(a2()); // return 2
0
morteza ataiy

これは明確な例制御タイムピッカーに基づいています_eworld.ui_ www.eworldui.net

JavaScriptが外部から到達できないTimePicker _eworld.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);
}
_

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

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

0

絶対に。新しい関数を割り当ててください。

0

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

a = function() { return 2; }
0
Wayne Koorts

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

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

0
Jon Onstott