简体   繁体   English

ES6类与ES5风格有多大差异?

[英]How much ES6 classes differ from ES5 style?

I'm that kind of a person who needs to know everything in depth... So, I've been going through many taught subjects and I set my foot into depths of Prototype-inheritance. 我就是那种需要深入了解一切的人......所以,我一直在经历许多教学科目,并且我已经深入了解原型继承。
I have a clear vision of how it works in ES5 (Every function has this special prototype property, which points to an object on which it is based on. This object has .constructor property, which points back to the function etc.). 我清楚地了解它在ES5中是如何工作的(每个函数都有这个特殊的原型属性,它指向它所基于的对象。这个对象有.constructor属性,它指向函数等)。

So, now let's see ES5 example: 那么,现在让我们看一下ES5示例:

function Bunny(name) {
    this.name = name
}

Bunny.prototype.sayName = function() {
    console.log('Im',this.name)
}

This one is pretty clear: function Bunny gets argument name which's going to be assign to a new object. 这个很清楚:函数Bunny获取的参数name将被分配给一个新对象。

Next line adds function to the function's prototype, which's going to return current name. 下一行将函数添加到函数的原型中,该函数将返回当前名称。

Let's see ES6 class now: 我们现在看看ES6课程:

class Fox{
    constructor(name){
        this.name = name;
    }

    sayName() {
        console.log('Im', this.name)
    }
}

Same stuff here: Constructor here is like our Bunny function. 同样的东西:这里的Constructor函数就像我们的Bunny函数。 But sayName in fox is not the same as sayName in Bunny. sayName在狐狸是不一样的sayName的兔子。
Let's create the instances: 让我们创建实例:

let bunny = new Bunny('Henry');
let fox = new Fox('Jerry');

And now, check their prototypes: 现在,检查他们的原型:

console.log(Object.getPrototypeOf(bunny))
console.log(Object.getPrototypeOf(fox))

What do we get? 我们得到了什么?

//using repl.it - ES6
{ sayName: [Function] }
{}

Why is that? 这是为什么?

I thought it might be because we set function sayName on Bunny's prototype directly. 我想可能是因为我们直接在Bunny的原型上设置了函数sayName So I've changed it to this: 所以我把它改成了这个:

function Bunny(name) {
    this.name = name

    //Warning - Bad practice ahead! 
    this.sayName = function() {
        console.log('Im',this.name)
    }
}

Result: 结果:

//using repl.it - ES6
{}
{}

That would have sense, if not this: 这有意义,如果不是这样:

console.log(bunny.hasOwnProperty('sayName'))
console.log(fox.hasOwnProperty('sayName'))

Which means, fox does not own sayName on him, either prototype shows it has it. 这意味着, fox没有对他拥有sayName ,原型显示它拥有它。 Am I missing something here? 我在这里错过了什么吗? Why They are different? 为什么他们不同?

In ES6 classes all methods are non-enumerable, so you when you log a prototype of an instance of an ES6 class, you get something that looks like an empty object. 在ES6类中,所有方法都是不可枚举的,因此当您记录ES6类的实例原型时,您会得到一个看起来像空对象的东西。

See this example: 看这个例子:

 const obj = new (class {method() {}}); console.log(Object.getPrototypeOf(obj)); // {} console.log(typeof Object.getPrototypeOf(obj).method); // function 

In ES5 you define a method by assigning it to a property of the class prototype, which makes it enumerable. 在ES5中,您可以通过将方法分配给类原型的属性来定义方法,这使其可枚举。 If you wanted to achieve the same effect as with ES6 classes, you could use Object.defineProperty() instead: 如果要实现与ES6类相同的效果,可以使用Object.defineProperty()代替:

 const TestClass = function TestClass() {}; Object.defineProperty(TestClass.prototype, 'method', { value: function() {}, writable: true, enumerable: false, configurable: true, }); const obj = new TestClass(); console.log(Object.getPrototypeOf(obj)); // {} console.log(typeof Object.getPrototypeOf(obj).method); // function 


And fox.hasOwnProperty('sayName') returns false because hasOwnProperty() checks only for own properties, and sayName is in the prototype chain. 并且fox.hasOwnProperty('sayName')返回false因为hasOwnProperty()仅检查自己的属性,而sayName在原型链中。 If you want to check for properties in the prototype chain too, you can use the in operator: 'sayName' in fox returns true . 如果你想检查原型链中的属性,可以使用in运算符: 'sayName' in fox返回true


See also Enumerability and ownership of properties on MDN. 另请参阅MDN上的属性的可用性和所有权

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM