JavaScript绑定方法不适用于getter属性

时间:2016-06-22 16:11:29

标签: javascript

尝试这样做:

var c = {
  x: 'other context'
};

var o = {
  x: 'this context',
  get otherContext () {
    alert(this.x);
  }.bind(c)
};

o.otherContext;

但我得到Syntax Error

  

未捕获的SyntaxError:意外的令牌

用例

您可能会问,为什么我可能想要更改getter上下文。在这里引导我的用例涉及创建一个将检索DOM属性的辅助对象。帮助器是在另一个对象中定义的,该对象持有对我需要属性的DOM元素的引用。所以,这个辅助对象实际上只是一些DOM方法的代理,实际上,我会做类似的事情:

var ViewObject = function () {
  this.el = document.getElementById('id');

  var proxy = {
    ...
    get left() {
      return this.el.offsetLeft
    }.bind(this)
    ...
  };
};

恕我直言,这是一个非常有效的用例。拥有父对象的this上下文的一个有用。 (也许代理功能可能更合适?嗯......我没有想到这一点。仍然是吸气剂是ES5,代理是ES6,只有常青树和Edge 13+实现,我认为在ES5的范围内问题仍然很非常适用。)

有人可以给我一个合乎逻辑的解释(优先考虑规范)为什么更改getter的上下文是非法的。

2 个答案:

答案 0 :(得分:11)

问题是method syntax没有使用函数表达式。它是一个定义的句法结构。

  

MethodDefinition [Yield]

     
    

PropertyName [?收益率] StrictFormalParameters { 功能体 }

         

GeneratorMethod [?收率]

         

获取 PropertyName [?收益率] { 功能体 }

         

设置 PropertyName [?收益率] PropertySetParameterList { 功能体 }

  
     

PropertySetParameterList

     
    

FormalParameter

  

由于它不是函数表达式,因此您无权访问函数方法或属性。

您可以使用Object.defineProperty完成所需内容。

var proxy = { ... };
Object.defineProperty(proxy, 'left', {
  get: function() {
    return this.el.offsetLeft;
  }.bind(this)
});

答案 1 :(得分:3)

对于类代理,您可能希望使用以下内容:

class Main {
    constructor() {
        this._adapter = new Adapter();
        return this._createProxy();
    }

    _createProxy() {
        return new Proxy(this, {
            get(me, propertyName) {
                if (typeof me._adapter[propertyName] === 'function') {
                    return me._adapter[propertyName].bind(me._adapter);
                }
                return (function () {
                    return me._adapter[propertyName];
                }.bind(me._adapter))();
            }
        });
    }
}

class Adapter {
    constructor() {
        this._foo = true;
        this._yuk = 2;
    }

    get foo() {
        return this._foo;
    }

    baz() {
        return 4*this._yuk;
    }
}

这样,getter和方法都将包含在正确的上下文中:

let main = new Main();
console.log(main.foo);   // -> true
console.log(main.baz()); // -> 8