質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

2回答

1038閲覧

javascriptで定義済みの関数内のスコープの範囲を変えたい

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2016/10/12 06:08

編集2016/10/12 06:09

少し特殊な事情があり,以下のように引数を使わずに、bindした関数のスコープの中で定義済みの関数のスコープ内の変数を書き換えて動作させる方法があるかどうか調べています。

javascript

1function test(){ 2 return aa + bb; 3}; 4 5var z = (function(aa,bb){ 6 return test(); 7})(2,3) 8 9理想の結果 10 11z=5 12

上記のコードはうまくいきません。test.bind({aa:aa,bb:bb})()としても上位スコープの変数にアクセスできませんでした。
このような動作をさせることは不可能でしょうか。目的は,ダミーコードでありますが,実際の開発コード上で上記のtestにあたるような関数を書き換えたくないという意図があります。
もし実装する方法が思いつく方いらっしゃれば教えていただけると嬉しいです。よろしくお願い足します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

JavaScript

1"use strict"; 2var aa; 3var bb; 4 5function test(){ 6 return aa + bb; 7}; 8 9var z = (function(_aa,_bb){ 10 var pre_aa = aa; 11 var pre_bb = bb; 12 var result; 13 aa = _aa; 14 bb = _bb; 15 result = test(); 16 aa = pre_aa; 17 bb = pre_bb; 18 return result; 19})(2,3); 20 21console.log(z);
  1. 無名関数の引数やローカル変数としてaabbを定義してはいけない。もし、定義してしまうと外側のaabbにアクセスできなくなる。
  2. 別名の引数からaabbに代入する。こうすることで、test()で使うaabbに指定の値を入れられる。
  3. 単純に代入だけしてしまうと、aabbに対する副作用が発生してしまう。もともとのaabbの値を別のローカル変数に入れておき、実行後に元に戻すようにする。
  4. aabbを元に戻す処理を入れるためには、すぐにreturnで返せない。また別のローカル変数に結果を入れておき、最後にretrunを返す。

ぶっちゃけて言うとtest()自体が作りが悪い関数です。書き換えたくないとのことですが、今のコードを全て捨てて、いっそ全部書き換えた方が早いかも知れません。

投稿2016/10/12 13:26

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/10/12 15:46 編集

ぶっちゃけそうですよね。基本的に副作用が前提のコードなんて書いちゃいけないと思います。 詳しくは言えないのですが特殊な事情があってこう言う実装になっています。 もっと言うとglobal変数が処理の段階で何度も書き換わるのでそれぞれの時点でbindしなければならず、構造を変えれば簡単に実装出来ると思いますが、変えないで出来ないかという依頼があったので一応調査しました。 これ出来てしまったらいくらでもコード壊せますもんね。ありがとうございました。
guest

0

外部スコープから内部スコープを参照する

スコープ外から変数を書き換えることは不可能なので、予め内部に書き換える仕組みを作ってみてはどうでしょうか。

JavaScript

1var test = (function (a, b) { 2 function test () { 3 return a + b; 4 } 5 6 test.set = function set (_a, _b) { 7 a = _a; 8 b = _b; 9 }; 10 11 return test; 12})(2, 3); 13 14test.set(4, 5); 15console.log(test()); // 9

このコードは深く考えずに書きましたが、筋の良い書き方とは私も思いません。
無名関数内に閉じ込められていたローカル変数 a, b がグローバルスコープから参照できるようになっているわけですが、
これは例えるなら、「ローカル変数がグローバル変数に化けている」ようなものだからです。

(代替案) インスタンスプロパティに値を代入する

後で書き換える意図があるならオブジェクト指向的に関数を定義するのが良いと思います。

JavaScript

1function Foo (a, b) { 2 this.a = a; 3 this.b = b; 4} 5 6Object.defineProperty(Foo.prototype, 'test', { 7 writable: true, 8 enumerable: false, 9 configurable: true, 10 value: function test () { 11 return this.a + this.b; 12 } 13}); 14 15var foo = new Foo(2, 3); 16console.log(foo.test()); // 5 17foo.a = 4; 18foo.b = 5; 19console.log(foo.test()); // 9

getter, setter 的なプロパティを定義すれば更に複雑な動作も実現できます。

Re: tkow さん

投稿2016/10/12 10:27

編集2016/10/12 14:34
think49

総合スコア18164

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2016/10/12 15:51

ありがとうございます。 これでもテスト関数のスコープ範囲変える必要があるので駄目でした。 結論としては良くないコードなので先方の要求を却下しようと思います。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問