为什么JavaScript对象没有';t获取ES6中数据和方法的副本

为什么JavaScript对象没有';t获取ES6中数据和方法的副本,javascript,class,design-patterns,ecmascript-6,es6-class,Javascript,Class,Design Patterns,Ecmascript 6,Es6 Class,面向对象设计(在大多数语言中,尤其是Java中)的一个常见方面是,当我们使用构造函数构造新对象时,所有方法和公共/受保护的实例变量都被复制到对象中。例如: Car myCar = new Car('Corolla', '2015'); 现在,如果Car类具有goForward()或goBackward()方法,则所有这些方法都将被复制到myCar对象 但就我所研究的JavaScript而言,情况并非如此。如果这在JavaScript中是类似的,myCar的原型实际上指向Car原型 根据我的理解

面向对象设计(在大多数语言中,尤其是Java中)的一个常见方面是,当我们使用构造函数构造新对象时,所有方法和公共/受保护的实例变量都被复制到对象中。例如:

Car myCar = new Car('Corolla', '2015');
现在,如果
Car
类具有
goForward()
goBackward()
方法,则所有这些方法都将被复制到
myCar
对象

但就我所研究的JavaScript而言,情况并非如此。如果这在JavaScript中是类似的,
myCar
的原型实际上指向
Car
原型

根据我的理解,如果我们想使用类继承作为设计模式,那么这种数据和方法的复制是最终的要求。JavaScript真的缺少这个特性,还是我的理解很模糊?新的基于ES6类的结构是否将这一点带入了人们的视野


感谢您澄清我的概念,我对此感到非常困惑,因为我过去一直在用Java做事情。

在Javascript中,构造函数包含一个
.prototype
属性,该属性包含为该对象定义的任何方法(在ES5中直接分配给原型,或者在ES6中使用
class
关键字)

然后,当您使用该构造函数实例化一个新对象时,该对象将被赋予一个指向原型的指针。当对该对象调用一个方法时,Javascript解释器将首先在该对象本身上查找具有该名称的属性,如果在那里找不到,它将搜索原型链

因此,在Javascript中,“复制”到新创建对象的唯一内容是指向原型的指针。这在ES5和ES6中的作用相同。ES6中的
class
语法只是我们在ES5中手动执行的新语法(将方法分配给原型对象)

事实上,如果需要,您甚至可以使用
Object.getPrototypeOf()
获取原型。重要的是要认识到新对象包含指向原型对象的指针(而不是副本)。如果对原型对象进行后续更改,则它是“活动的”,并且之前或之后的所有实例化对象都将看到该更改

class Car {
    constructor(brand, model) {
        // initialize instance data
        this.brand = brand;
        this.model = model;
    }
    goForward() {
        console.log("goForward");
    }
    goBackward() {
        console.log("goBackward");
    }
}

let c = new Car("Toyota", "Corolla");
console.log(Object.getPrototypeOf(c));    // shows the two methods goForward, goBackward
console.log(c.brand);      // "Toyota"
现在,如果Car类有goForward()或goBackward()方法,则所有这些方法都将被复制到myCar对象

给新对象一个指向原型的指针。这些方法不会单独复制

根据我的理解,如果我们想使用类继承作为设计模式,那么这种数据和方法的复制是最终的要求

<>这不是真的。继承不需要复制所有方法到新对象。实际上有很多不同的方法来实现正确的继承。JavaScript使用一个原型。C++使用编译时绑定。我自己不知道java的内部结构,但引用了一个方法表,它给java中的每个对象提供了指针T。o

新的基于ES6类的结构是否将这一点带入了人们的视野


ES6并没有改变继承在Javascript内部的工作方式。ES6只是引入了
语法,这是一种声明对象构造函数和方法的不同方式,但它产生了与我们在ES5原型上手动声明方法相同的内部结构。

我不太明白这个问题。在大多数情况下OOP语言,当你实例化一个类的新实例时,方法不会被复制到它,只是设置了对象的类,当你调用一个方法时,有一种机制可以在相关的类及其超类中搜索它。这在javascript中也是一样的,只是你有一个原型而不是class.ES6类只是语法糖,它相当于在纯JS中做一辆
新车(…)
,看一看——事实上你的理解似乎太模糊了。在没有严肃的OOP语言中,每个方法都被复制到每个实例:在Java中,编译器做了一些魔术,让你调用
myCar.goBackward()
,而在JavaScript中,它是一个完全透明的运行时构造,允许您执行
myCar.goBackward()
。它根本不影响设计-它只是更灵活而已,ES6
class
没有带来新的结构,它只带来了新的语法-继承如何工作的概念没有改变。