1. ホーム
  2. javascript

[解決済み] JavaScriptの関数エイリアシングがうまくいかない

2023-04-03 02:43:19

質問

私はちょうど この質問 を読んでいて、function-wrapper方式ではなくalias方式を試したかったのですが、Firefox 3または3.5beta4、あるいはGoogle Chromeで、デバッグウィンドウとテストWebページの両方で動作させることができなかったようです。

Firebug です。

>>> window.myAlias = document.getElementById
function()
>>> myAlias('item1')
>>> window.myAlias('item1')
>>> document.getElementById('item1')
<div id="item1">

Webページに入れると、myAliasを呼び出すとこのようなエラーが発生します。

uncaught exception: [Exception... "Illegal operation on WrappedNative prototype object" nsresult: "0x8057000c (NS_ERROR_XPC_BAD_OP_ON_WN_PROTO)" location: "JS frame :: file:///[...snip...]/test.html :: <TOP_LEVEL> :: line 7" data: no]

Chrome(わかりやすいように>>を挿入しています)。

>>> window.myAlias = document.getElementById
function getElementById() { [native code] }
>>> window.myAlias('item1')
TypeError: Illegal invocation
>>> document.getElementById('item1')
<div id=?"item1">?

そしてテストページでは、同じように"Illegal invocation"が表示されます。

私は何か間違ったことをしているのでしょうか? 誰かこれを再現できる人はいますか?

また、不思議なことに今試してみたところ、IE8で動作しました。

解決方法は?

そのメソッドをドキュメントオブジェクトにバインドする必要があります。見てください。

>>> $ = document.getElementById
getElementById()
>>> $('bn_home')
[Exception... "Cannot modify properties of a WrappedNative" ... anonymous :: line 72 data: no]
>>> $.call(document, 'bn_home')
<body id="bn_home" onload="init();">

単純なエイリアスを行う場合、関数はドキュメントオブジェクトではなく、グローバルオブジェクト上で呼び出されます。これを解決するためにクロージャというテクニックを使います。

function makeAlias(object, name) {
    var fn = object ? object[name] : null;
    if (typeof fn == 'undefined') return function () {}
    return function () {
        return fn.apply(object, arguments)
    }
}
$ = makeAlias(document, 'getElementById');

>>> $('bn_home')
<body id="bn_home" onload="init();">

この方法では、元のオブジェクトへの参照を失うことはありません。

2012年には、新しい bind メソッドが ES5 から導入され、よりファンシーな方法でこれを行うことができるようになりました。

>>> $ = document.getElementById.bind(document)
>>> $('bn_home')
<body id="bn_home" onload="init();">