2016-07-07 13 views
2

スコープに問題があります。関数の外側にある "var text"を宣言すると、すべて動作します。しかし、関数の中では、最初の部分でのみ動作します。ここに私が意味するものがあります:関数の可変スコープ

これはバッファ機能です。バッファ(「何か」)を実行すると「何か」が保存されます。プロパティなしでbuffer()を実行すると、すべてのプロパティが返されます。

  • バッファ( "アル")
  • バッファ( "EX")
  • バッファー()<は=アレックス

しかし、 "テキスト" のSCOPEを返す必要が間違っているとそれはありません保存されたプロパティを返しません。正常な動作です

function makeBuffer() { 
 
    var text = ""; 
 
    if (arguments.length != 0) { 
 
     for (let i = 0; i < arguments.length; i++) { 
 
     console.log(`Adding argument - (${arguments[i]})`); 
 
     text += arguments[i]; 
 
     console.log(`New text - (${text})`); 
 
     } 
 
    } else { 
 
     console.log(`text - (${text})`); 
 
     return text; 
 
    } 
 
    } 
 
    var buffer = makeBuffer; 
 

 

 
    buffer("One", "Two"); 
 
    document.write(buffer());

答えて

5

スコープがなくなると、特定のスコープで定義された変数がなくなります。関数を呼び出すたびに新しいスコープが作成されます。

関数の外部で変数を宣言することは、関数の呼び出し間で値を共有するための標準的な方法です。あなたがオブジェクトを使用してこれを行うことが

function makeBuffer() { 
 
    var text = ""; 
 
    
 
    return function buffer() { 
 
    if (arguments.length != 0) { 
 
     for (let i = 0; i < arguments.length; i++) { 
 
     console.log(`Adding argument - (${arguments[i]})`); 
 
     text += arguments[i]; 
 
     console.log(`New text - (${text})`); 
 
     } 
 
    } else { 
 
     console.log(`text - (${text})`); 
 
     return text; 
 
    } 
 
    } 
 
} 
 

 
var buffer = makeBuffer(); 
 

 
buffer("One", "Two"); 
 
document.write(buffer());

3

は何が欲しいの工場です。これにより、コードがより整理されます。

class Buffer { 
 
    constructor() { 
 
    this.text = ""; 
 
    } 
 
    append() { 
 
    this.text = this.text.concat(...arguments); 
 
    } 
 
    get() { 
 
    return this.text; 
 
    } 
 
} 
 

 
var buffer = new Buffer(); 
 
buffer.append("One", "Two"); 
 
document.write(buffer.get());

+2

という名前の関数を返すために必要はありません: 'リターン機能バッファー()' – RomanPerekhrest

+2

@RomanPerekhrestを - あなたはそれを呼び出すことを期待しますか、それを返さない場合は? – Quentin

+1

@クエンティン彼は、単に機能に名前を付ける必要がないことを意味します。 'return function()' – 4castle

1

+0

ES6実装の 'get'キーワードが期待通りに機能するのに驚いています。私は通訳者が 'SyntaxError:Unexpected token '(' ' –

+0

@PatrickRoberts私は同意しますが、関数名と組み合わせて使用​​すると唯一のキーワードです。 – 4castle

1

クエンティンが適切に彼の答えで指摘したように、それは正常な動作です:構文も甘くなるES6を使用して

var Buffer = function() { 
 
    this.text = ""; 
 
} 
 
Buffer.prototype.append = function() { 
 
    for (var i = 0; i < arguments.length; i++) { 
 
    this.text += arguments[i]; 
 
    } 
 
} 
 
Buffer.prototype.get = function() { 
 
    return this.text; 
 
} 
 

 
var buffer = new Buffer(); 
 
buffer.append("One", "Two"); 
 
document.write(buffer.get());

に保つための別のオプションは、変数を外部に宣言することなくスコープをプロパティとしてプロパティに追加することです。

JavaScriptのように、ファンクションはファーストクラスのオブジェクトなので、そのようなデータを関数オブジェクト(他のオブジェクトのように)に直接入れることができます。

以下の例は、機能(buffer.text)からプロパティtextを取得する方法に注意してください。

function makeBuffer() { 
 
    makeBuffer.text = ""; 
 
    if (arguments.length != 0) { 
 
    for (let i = 0; i < arguments.length; i++) { 
 
     console.log(`Adding argument - (${arguments[i]})`); 
 
     makeBuffer.text += arguments[i]; 
 
     console.log(`New text - (${makeBuffer.text})`); 
 
    } 
 
    } else { 
 
    console.log(`text - (${makeBuffer.text})`); 
 
    return makeBuffer.text; 
 
    } 
 
} 
 

 
var buffer = makeBuffer; 
 

 
buffer("Al", "ex"); 
 
console.log(`buffer.text - (${buffer.text})`);

代わりに関数呼び出しの間のテキストの値を維持するために、クロージャを使用することを検討してください。

Closures are functions that refer to independent (free) variables (variables that are used locally, but defined in an enclosing scope). In other words, these functions 'remember' the environment in which they were created. More info here .

let makeBuffer = function() { 
 
    // closure 
 
    let text = ""; 
 
    return function() { 
 
    if (arguments.length != 0) { 
 
     for (let i = 0; i < arguments.length; i++) { 
 
     console.log(`Adding argument - (${arguments[i]})`); 
 
     text += arguments[i]; 
 
     console.log(`New text - (${text})`); 
 
     } 
 
    } else { 
 
     console.log(`text - (${text})`); 
 
     return text; 
 
    } 
 
    } 
 
}; 
 
var buffer = makeBuffer(); 
 
buffer("Al", "ex");

関連する問題