【问题标题】:Any other solution for context resolution this in promises except bind除了 bind
【发布时间】:2016-07-02 08:46:01
【问题描述】:

这种情况下的任何横向解决方案,当我需要知道我在哪个类而不使用绑定时。

function Customer() {}
Customer.prototype.say = function() {
    console.log("I'm " + this.constructor.TYPE);
};
Customer.TYPE = 'customer';

function Product() {}
Product.prototype.say = function() {
    console.log("I'm " + this.constructor.TYPE);
};
Product.TYPE = 'product';

var customer = new Customer();
var product = new Product();

//cleaner interface
Promise.resolve()
    .then(customer.say) //I'm undefined
    .then(product.say) //I'm undefined


//works but looking for a solution using cleaner interface like above
//any lateral thinking
Promise.resolve()
    .then(customer.say.bind(customer)) //I'm customer
    .then(product.say.bind(product))  //I'm product

我正在寻找基于非绑定的解决方案,任何基于横向思维的想法?

这是我正在开发的 SDK,因此希望提供更简洁的界面并供客户使用。

【问题讨论】:

  • 您必须使用bind 或匿名函数,不确定您还期望什么...
  • 有什么方法可以在保持语法简洁的同时了解调用者的类型?
  • "在全局范围内调用" 不,调用时this指的是全局对象(或严格模式下的undefined),与此无关范围。
  • 使用函数而不是方法并显式传递对象,那么您将摆脱bind和this
  • @LUH3417 抱歉没找到你,怎么样?

标签: javascript static promise this


【解决方案1】:

你基本上有三个选择:

  1. bind,你说过你不想要。

  2. 这样的包装函数:

    .then(function(r) { return customer.say(r); })
    

    ...在 ES2015 中可能如下所示:

    .then(r => customer.say(r))
    
  3. 更改您的对象,使它们不再使用从原型继承的函数,而是关闭实例的特定于实例的函数:

    在 ES5 及更早版本中:

    var Customer = function() {
        var me = this;
        me.say = function() {
            console.log("I'm " + me.constructor.TYPE);
        };
    };
    

    在 ES2015+ 中

    var Customer = function() {
        this.say = () = {
            console.log("I'm " + this.constructor.TYPE);
        };
    };
    

    您最终会以这种方式创建更多函数对象,但函数中的代码将被 JavaScript 引擎重用。

有一个 proposal to the TC39 committee that defines JavaScript 用于执行您想要的操作(基本上是 bind,但语法更简洁),但它仅处于第 0 阶段,因此不太可能出现在 ES2017 中。

【讨论】:

  • 当你说,你最终会以这种方式创建更多的函数对象,这意味着每个对象都有自己的 say 副本?
  • @user2727195:每个Customer 对象都有自己的say 函数对象。在任何现代 JavaScript 引擎上,该函数对象将与其他 Customer 实例具有的 say 函数对象共享底层代码,但是是的,它是每个实例的。如果同时有数十万个Customer 对象,这只是一个问题。
【解决方案2】:

一些想法:

1) 不要使用原型/类。他们会一遍又一遍地制造这种问题。相反,使用模块模式。由于每次都在闭包内创建“方法”,因此它们被有效地绑定:

function Customer() {
    function say() {}

    return {
        type: 'product',
        say
    }
}

2) 提供一个构造来构建基于原型的对象层次结构,其中所有方法都是预先绑定的。请注意,这消除了原型的唯一优势:内存消耗略少。

3) 冒险并使用 babel 提供的 :: 表示法: 然后(::customer.say) 诚然,并没有那么好,而且这个提议目前有点陈旧,所以它甚至可能不会正式进入语言。

【讨论】:

  • 你的回答有点帮助我发布我的答案:)
  • 我认为是因为你的return语句不完整,会有错误。
  • 我是这个模块模式的新手,一直在使用基于原型的,我们可以使用基于模块的模式进行继承吗?
  • "inheritance" 在使用模块模式时将简单地包括复制内部另一个对象的所有功能。就是说,我可以建议在谷歌上查找“组合而不是继承”这句话吗? :D 最好的建议。
猜你喜欢
  • 2014-10-25
  • 1970-01-01
  • 2013-10-03
  • 1970-01-01
  • 2016-05-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-11
相关资源
最近更新 更多