【问题标题】:Do ES2015 Classes "not autobind"?ES2015 类“不自动绑定”吗?
【发布时间】:2016-10-29 00:43:05
【问题描述】:

我使用 React 已经有一段时间了,我已经习惯了我必须手动将我的组件方法绑定到我的组件实例的概念,因为 React 决定不自动绑定是“惯用的”:

因此我们决定不将这个内置到 React 的类中 模型。您仍然可以在构造函数中显式预绑定方法,如果 你想要的。

class Counter extends React.Component {
  constructor() {
    super();
    this.tick = this.tick.bind(this);
  }
  tick() {
    ...
  }
  ...
}

-https://facebook.github.io/react/blog/2015/01/27/react-v0.13.0-beta-1.html

我们可以从这个类似的问题http://jsbin.com/citafaradu/2/edit?js,console,output 中清楚地看到这个例子的效果:How to properly bind current object context in ES6 using babelify

但是,最近有人问我基于原型的类和新的 ES2015 类之间是否有任何区别。直观地说,这个答案应该是一个强调的“不!”,因为生成的实例对象自然会有正常的原型并且行为......嗯,就像 JS 对象一样!此外,不绑定到实例的实例方法有什么用?

我试图寻找任何迹象表明这对于 es6 类来说是“惯常的”,但我发现的只是来自 React 开发人员的其他问题,答案如下:

React 的 ES6 类没有自动绑定。这记录在这里: https://facebook.github.io/react/docs/reusable-components.html#no-autobinding

原因是 javascript 的 ES6 类没有自动绑定 也没有[原文如此]。 React 试图不重新发明已经存在的东西 javascript。 ES5 没有很好的类语法,所以 React 不得不发明 它是自己的课程。但是现在有了 ES6 类,我们可以只使用标准 javascript。
- “科迪”,https://github.com/facebook/react/issues/4065

现在我真的很困惑。这可能是 JSX 转译的一个技巧吗?看一下前面例子的 render 方法的输出:

{
    key: "render",
    value: function render() {
      return React.createElement("div",null,
        React.createElement("input", { 
          type: "text", onChange: this.handleBindedChange 
        }),
        React.createElement("br", null),
        React.createElement("input", { 
          type: "text", onChange: this.handleUnbindedChange 
        }),
        React.createElement("br", null),
        React.createElement("p",null,"Result: ",this.state.demo)
     );
    }
 }

这里也没有骰子 - babel 输出使用 Object.defineProperty,它绝对会将添加的函数绑定到它们所附加的对象。

所以,我不知所措。我发现的大多数回复都比最终的 es2015 规范更老——因为我在规范本身中找不到任何关于它的内容,是否有任何改变会使 React 团队的方法无效?这是我以某种方式误解的奇怪的编译器吗?反应是否在幕后做了一些古怪的事情来导致这种情况?如果是这样,为什么他们会一再声称这样做是为了符合 ES2015 标准?如果不是,是什么导致了给出的第一个示例中的行为?

【问题讨论】:

  • 我不确定你的意思。 Object.defineProperty 不会“自动绑定”,调用函数会根据函数的调用方式设置this,与其他任何地方一样。
  • @loganfsmyth,Object.defineProperty 并不是我真正关心的,就像人们一开始甚至会谈论“自动绑定”一样——讨论它的方式可能是来源我的困惑。
  • 你可能想看看over here

标签: javascript reactjs ecmascript-6


【解决方案1】:

我也有类似的问题。您的类中的方法将能够引用同一类中的其他方法,因为它们属于同一上下文 (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this)。

这个例子表明类中的方法可以访问this 上的属性,而无需在构造函数中绑定:http://jsbin.com/tapokotahi/1/edit?js,console,outputrenderElements 方法未绑定,但正在访问 this.state

类方法在传递到事件处理程序时需要绑定(或定义为箭头函数),因为执行上下文从类的上下文更改为事件处理程序的上下文。

我同意,当我们阅读 React 文档并告诉我们需要在构造函数中绑定方法时,这似乎令人困惑,但这仅在将方法传递给 React 的事件处理程序(例如 onClick)时才有必要。

【讨论】:

  • 是的,他们给出的一些例子让我把头发拔了出来。惊喜,它还是我们熟悉和喜爱的旧 this。必须自己解决:jsfiddle.net/zf83ktm1/1
  • @MaxPRafferty "same old this" - 正是这个想法
【解决方案2】:

React 一直提到自动绑定的原因是因为React.createClass 是自动绑定所有方法。而这种方法是创建组件的唯一方法。

人们,尤其是那些不熟悉 JavaScript 的人,习惯于将方法传递给其他组件,this 会“神奇地”工作。这个特性在使用原生 ES6 类时消失了,所以他们需要强调区别。

但是,是的,ES6 类基本上只是构造函数 + 原型的语法糖。方法未绑定到对象:

class Foo {
  bar() {}
}

const foo = new Foo();

console.log(foo.hasOwnProperty('bar')); // false
console.log(typeof Foo === 'function'); // true
console.log(Foo.prototype.hasOwnProperty('bar')); // true

【讨论】:

【解决方案3】:

你可以让你的 ES6 类方法在构造函数中自动绑定一个小样板:

function autobind() {
  for (let prop of Object.getOwnPropertyNames(Object.getPrototypeOf(this))) {
    if (prop === 'constructor' || typeof this[prop] !== 'function') continue;
    this[prop] = this[prop].bind(this);
  }
}

class Test {
  constructor() {
    autobind.call(this);
    this.message = 'hello all!';
  }
  method1(){ return this.method2(); }
  method2(){ console.log(this.message);}
}
let test = new Test();
let b = test.method1;
b();

更新:

我后来找到了一个Babel Plugin,它可以翻译升级的 ES 类字段和静态属性,您可以将其用于需要绑定到 this 的函数

class Bork {
    //Property initializer syntax
    instanceProperty = "bork";
    boundFunction = () => {
      return this.instanceProperty;
    }

    //Static class properties
    static staticProperty = "babelIsCool";
    static staticFunction = function() {
      return Bork.staticProperty;
    }
}

let myBork = new Bork;

//Property initializers are not on the prototype.
console.log(myBork.__proto__.boundFunction); // > undefined

//Bound functions are bound to the class instance.
console.log(myBork.boundFunction.call(undefined)); // > "bork"

//Static function exists on the class.
console.log(Bork.staticFunction()); // > "babelIsCool"

【讨论】:

    【解决方案4】:

    我遇到了方法不自动绑定到类的问题。我做了一个图书馆来帮忙:https://www.npmjs.com/package/auto-bind-inheritance

    我使用它并感谢任何反馈以改进它。它基于其他几个 npm 包,我相信我对其进行了改进。

    【讨论】:

      【解决方案5】:

      Auto Binding.

      这个库在 Node.js 中对我来说运行良好。但我不确定这是否适用于 React.js。

      const AUTO_BIND = require("auto-bind");
      
      class Programmer {
      
        constructor(name, age) {
          this.Name = name;
          this.Age = age;
          AUTO_BIND(this);
          //* For React component
          //* AUTO_BIND.react(this);
        }
      
        ShowName() {
          console.log(`My name is ${this.Name}`);
        }
      
        ShowAge() {
          console.log(`My age is ${this.Age}`);
        }
      
        ShowDetail() {
          this.ShowName();
          this.ShowAge();
        }
      }
      const programmer = new Programmer("M. Hamza Rajput", 25);
      
      const { ShowDetail } = programmer;
      
      ShowDetail();
      
      console.log(programmer.hasOwnProperty('ShowDetail')); // true
      console.log(typeof programmer === 'object'); // true
      console.log(Programmer.prototype.hasOwnProperty('ShowDetail')); // true
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-10-18
        • 2016-10-14
        • 1970-01-01
        • 2012-03-10
        • 2016-02-23
        相关资源
        最近更新 更多