4

関数参照「go」を別の関数「redefineFunction」に渡し、「redefineFunction」内で「go」を再定義したい。Johnathan Snook によると、関数は参照によって渡されるため、redefineFunction() に渡したときに go() が再定義されない理由がわかりません。私が見逃しているものはありますか?

// redefineFunction() will take a function reference and
// reassign it to a new function
function redefineFunction(fn) {
    fn = function(x) { return x * 3; };
}

// initial version of go()
function go(x) {
    return x;            
}

go(5); // returns 5

// redefine go()
go = function(x) {
     return x * 2;        
}

go(5); // returns 10

// redefine go() using redefineFunction()
redefineFunction(go);

go(5); // still returns 10, I want it to return 15

または、私のフィドルhttp://jsfiddle.net/q9Kft/を参照してください

4

8 に答える 8

8

衒学者は、JavaScript は純粋な値渡しであると言うでしょうが、(オブジェクトを渡すときに) 渡される値はそのオブジェクトへの参照であるため、問題を曇らせるだけだと思います。したがって、オブジェクトのプロパティを変更すると、元のオブジェクトが変更されますが、変数を完全に置き換えると、基本的に元のオブジェクトへの参照が放棄されます。

グローバル スコープで関数を再定義しようとしている場合: (これは悪いことです。通常、グローバル関数は使用しないでください)。

function redefineFunction(fn) {
    window[fn] = function() { ... };
}

redefineFunction('go');

それ以外の場合は、新しい関数を返し、呼び出し側で割り当てる必要があります。

function makeNewFunction() {
    return function() { ... };
}

go = makeNewFunction();
于 2012-05-10T14:01:32.503 に答える
2

JSでは「参照によって渡される」ものはありません。参照が渡されることもありますが、値によって渡されます。違いは微妙ですが重要です。1つには、参照されるオブジェクトをほぼ自由に操作できますが、呼び出し元が行う方法でオブジェクトを確実に置き換える(参照自体を変更する)ことができないことを意味します。を参照してください(参照は値によって渡されたため、元の参照のコピーにすぎません。再割り当てを試みると、argが数値または文字列の場合と同じように中断されます)。

一部のカウボーイは、グローバル関数を再定義していると想定し、値渡しの制限を回避するために名前でそれをいじりますが、それは、あなたがグローバルをあちこちに持たないと決めた瞬間に問題を引き起こします。

本当の解決策:新しい関数を返し、呼び出し元にそれをどうするかを決定させます。(関数を使用するコードの下から関数を再定義することは、とにかくかなり悪い設計上の決定であると私は主張しますが、ええと、それには理由があると思います...

于 2012-05-10T13:59:43.770 に答える
1

スヌークは間違っています。そして、JavaScriptのすべてが値渡しであることを指摘するのは、まったく衒学的ではないと思います(@ josh3736 :)。Snook の記事では、これが完全に間違っています。プリミティブを渡すこととオブジェクトを渡すことは、まったく同じように機能します。これらは同等です:

var x = 2;
var y = x;
y = 3; //x is STILL 2.

function stuff(y){
  y = 3; //guess what. x is STILL 2
}

stuff(x);

///////////////////

var x = {stuff: 2};
var y = x;
y = {stuff: 3}; //x.stuff is STILL 2

function stuff(y){
  y = {stuff: 3}; //guess what. x.stuff is STILL 2
}

stuff(x);

これは重要。Java、C#、および MOST 言語はこのように機能します。そのため、C# には参照渡しが本当に必要な場合に備えて "ref" キーワードがあります。

于 2012-05-10T14:15:43.507 に答える
0

関数内から変数を変更することはできないため、簡単な解決策は、値を返し、次のように関数外に割り当てることです。

// log() just writes a message to the text area
function log(message) {
    $('#output').val($('#output').val() + message + "\n");
}

// redefineFunction() will take a function reference and
// reassign it to a new function
function redefineFunction() {
   newvalue = function(x) { return x * 3; };
   return newvalue;
}

// initial version of go()
function go(x) {
    return x;            
}

log(go(5)); // returns 5

// redefine go()
go = function(x) {
     return x * 2;        
}

log(go(5)); // returns 10

// redefine go() using redefineFunction()
go = redefineFunction();

log(go(5)); // returns 10, I want it to return 15
于 2012-05-10T14:00:21.917 に答える
0

関数は「値で渡される」と思います。log(f(5));関数内に配置すると15が出力されますが、後でredefineFunction呼び出すと10が出力されます。log(go(5))

関数を返すように変更redefineFunctionし、それを go ( go = redefineFunction()) に割り当てると、期待どおりに機能します。

于 2012-05-10T14:05:21.597 に答える
0

これは、何らかの関数に引数として渡すことで変数を再定義できるかどうかを尋ねるのと同じです。いいえ、再割り当てすることで再割り当てできます。この場合、redefineFunction関数を返すようにすると、次のように単純に割り当てることができますgo

function redefineFunction() {
    var fn = function(x) { return x * e; };
    return fn;
}

function go(x) {
    return x;
}

go = redefineFunction();

go(5); // return 15
于 2012-05-10T14:05:49.637 に答える
0

これはFirefoxで機能しています:

function redefineFunction(fn) {
    window[fn] = function(x) {
        return x * 3;
    }
};

function go(x) {
    return x;
};

alert(go(5));

go=function(x) {
    return x * 2;
}

alert(go(5));

redefineFunction('go');

alert(go(5));


その秘密は、go というグローバル関数が window.go および window["go"] とも呼ばれていることです。
これは、スタイル: element.style["overflow"] = "hidden"、および属性:
element["value"] = "hello there" でも使用できます。これは非常に役立つ知識です。

于 2012-05-10T14:15:29.683 に答える
0

なぜオブジェクトを使用しないのですか? このようなもの:

var o = {
    go: function( x ) {
        return x;
    },

    redefineFunction: function ( fn ) {
        if (typeof fn === 'function') {
            this.go = fn;
        }
    }
}

console.log(o.go(5)); // return 5

var fn = function (x) {
  return x * 2;
};

o.redefineFunction(fn);

console.log(o.go(5));​ //return 10

それが役に立てば幸い!

于 2012-05-10T14:17:16.043 に答える