53292


お世話になっております。

仕事でiOSのJavaScriptCoreを使っているのですが、以下のようなスクリプトを走らせた際に意図した挙動になりません。

[code]

    // JSコンテキストを作成
    JSContext context = new JSContext();
    // スクリプトの実行
    context.EvaluateScript("var hoge = { position:[0,0,0], update: function() { this.position[0] += 1; } };");
    // hogeオブジェクトの取り出し
    JSValue hoge = context[(NSString)"hoge"];
    // hoge.positionを出力
    Console.WriteLine(hoge[(NSString)"position"].ToString());
    // hoge.updateの呼び出し
    hoge.GetProperty("update").Call();
    // 変更後のhoge.positionの出力
    Console.WriteLine(hoge[(NSString)"position"].ToString());
    
[/code]

期待している出力結果は、

[code]

    [0,0,0]
    [1,0,0]
    
[/code]

なのですが、実際は

[code]

    [0,0,0]
    [0,0,0]
    
[/code]

のように何も変更されていません。

`update`の呼び出し方は[JSValue.Call(JSValue[]) Method](https://docs.microsoft.com/en-
us/dotnet/api/javascriptcore.jsvalue.call#JavaScriptCore_JSValue_Call_JavaScriptCore_JSValue___)を参考にしました。

気になって`update`の中身を`return this.position;`に書き換えると結果は`undefined`。  
さらに書き換えて`return this;`とするとグローバルオブジェクトが返ってきました。

JavaScriptでメソッド呼び出す場合、thisにはメソッドを持っているオブジェクトが入るはずですよね？

メソッド呼び出しの仕方が間違えているのかもしれません。  
原因を知りたいです。


CC BY-SA 4.0
2019-03-08T08:44:21.597
53291
2019-03-08T13:46:04.127
2019-03-08T13:46:04.127
4236
31396
question
javascript ios c#
JavaScriptCoreで実行するスクリプトにおけるthisの扱いがわからない


これを書きながら並行して調べてたらJSValueクラスにはどうやら`Invoke`メソッドなるものが存在した...。

[JSValue.Invoke(String, JSValue[]) Method](https://docs.microsoft.com/en-
us/dotnet/api/javascriptcore.jsvalue.invoke#JavaScriptCore_JSValue_Invoke_System_String_JavaScriptCore_JSValue___)

これを以下のように使うと、

[code]

    hoge.Invoke("update");
    
[/code]

次のように期待した結果が出ました！！

[code]

    [0,0,0]
    [1,0,0]
    
[/code]

メソッド内で`this`を使う場合は呼び方に気をつけないといけないですね。


CC BY-SA 4.0
2019-03-08T08:44:21.597
53292
2019-03-08T08:44:21.597
31396
53291
answer


自己解決されていますが、原因の部分を説明しておきます。JavaScriptCoreは何も関係ありません。

> JavaScriptでメソッド呼び出す場合、thisにはメソッドを持っているオブジェクトが入るはずですよね？

いいえ、違います。MDNの[`this`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/this)で

> **関数の`this` キーワード** は、JavaScript ではほかの言語と少々異なる動作をします。  
>  ほとんどの場合、`this` の値は、関数の呼ばれ方によって決定されます。  
>  関数が呼び出されるたびに異なる可能性があります。

等の説明がされている通りです。

[code]

    var hoge = { position:[0,0,0], update: function() { this.position[0] += 1; } };
    
[/code]

とあった場合に、

[code]

    hoge.update.call();  // hoge.GetProperty("update").Call();
    hoge.update();       // hoge.Invoke("update");
    
[/code]

では呼び出し方が異なるため`this`の内容も異なるということです。前者は[`Function.prototype.call()`](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call)です。

見ての通り、JavaScriptCoreはJavaScriptの仕様をなぞるようにAPI設計されているに過ぎません。


CC BY-SA 4.0
2019-03-08T13:45:44.673
53300
2019-03-08T13:45:44.673
4236
53291
answer