ややこしいのはthisではない:JS

続いて元記事JavaScriptのthisではまった - No Programming, No Lifeの方も。

JavaScriptのthisではまったのでメモしておきます。

とあるのですが、さきほどのid:katzchang氏も

元記事に対して「どのオブジェクト上で走るかの話で、javaのthisも同じっちゃ同じ。 」ってブクマコメントを残した

と指摘されているようにthisは関係ないように思います。
thisの意味はそんなに変わらなくて、どちらもメソッドの持ち主がthisです。jsの場合メソッド(関数)が代入可能で、このJavaにはない「メソッドを代入する」事がハマったポイントではないかと思いました。

<html>
<head>
<title>thisのテスト</title>
<script type="text/javascript">
var someObj = {
    name   : 'SomeObject',
    whoAmI : function() {
        alert('I am ' + this.name + '.')
    }
}
function init() {
    var button1 = document.getElementById('button1')
    var button2 = document.getElementById('button2')
    button1.onclick = someObj.whoAmI
    button2.onclick = function(){ someObj.whoAmI() }
}
</script>
</head>
<body onLoad="init()">
<button id="button1" name="ぼたん1">押してね1</button><br>
<button id="button2" name="ぼたん2">押してね2</button><br>
</body>
</html>

とやるとボタン1では「I am ぼたん1」と出て、ボタン2では「I am someObject」と出るという話です。

javascriptのオブジェクトがマップであり、メソッドもそのマップに関数を入れている事を思い出して、ちょっとMapらしく書き換えてみます。

<script type="text/javascript">
var someObj = {}
someObj['name'] = 'SomeObject'
someObj['whoAmI'] = function() {
        alert('I am ' + this.name + '.')
}

function init() {
    var button1 = document.getElementById('button1')
    var button2 = document.getElementById('button2')
    button1['onclick'] = someObj['whoAmI']
    button2['onclick'] = function(){ someObj.whoAmI() }
}
</script>

someObj['whoAmI']function() { alert('I am ' + this.name + '.') }なので、button1['onclick']function() { alert('I am ' + this.name + '.') }になります。

<script type="text/javascript">
var someObj = {}
someObj['name'] = 'SomeObject'
someObj['whoAmI'] = function() {
        alert('I am ' + this.name + '.')
}

function init() {
    var button1 = document.getElementById('button1')
    var button2 = document.getElementById('button2')
    button1['onclick'] = function(){ alert('I am ' + this.name + '.') }
    button2['onclick'] = function(){ someObj.whoAmI() }
}
</script>

button1.onclick()を呼び出せば、this.nameは「ぼたん1」となるわけです。

var someObj = {
    name   : 'SomeObject',
    whoAmI : function() { alert('I am ' + this.name + '.') }
}

とあって、

    button1.onclick = someObj.whoAmI

と書いたときに、それが

    button1.onclick = function(){ someObj.whoAmI() }

ではなく

    button1.onclick = function() { alert('I am ' + this.name + '.') }

という意味だ、というのがポイントなんだと思います。

function() {
    alert('I am ' + this.name + '.')
}

という関数オブジェクトは、「その時のオーナー(this)のnameというフィールドを使ってアラートする」という処理が行われるということです。

というのはそうなんですが、その時々のthisの意味に注目するよりも、メソッドメソッドを代入する、という事がどういう事なのか、に注目した方が良いのではないかと思います。
「オーナー(this)」というのはメソッドの持ち主のことで、それはJavaと変わりない。

ある関数の中でthisはオーナー(呼び出し主)を指している。

の「呼び出し主」がセンダー(メソッドの呼び出し元)の意味なら誤りで、「オーナー」に当たるのはJavaのthisと同じ、そのメソッドの持ち主なわけです。