所以我还在学习JavaScript,而且我现在正在使用原型。我刚刚完成的课程向我展示了如何使用__proto__
创建原型继承链。这是我的意思的一个例子:
function Person(firstName,lastName,dob){
this.firstName = firstName;
this.lastName = lastName;
this.dob = new Date(dob);
}
Person.prototype = {
constructor: Person,
getFullName: function(){
return this.firstName + " " + this.lastName;
},
getAge: function(){
var ageDiff = Date.now() - this.dob;
var ageDiffDate = new Date(ageDiff);
return Math.abs(ageDiffDate.getUTCFullYear() - 1970);
}
}
function Employee(firstName,lastName,dob,position,dept){
this.firstName = firstName;
this.lastName = lastName;
this.dob = new Date(dob);
this.position = position;
this.dept = dept;
this.isFired = false;
}
Employee.prototype = {
constructor: Employee,
__proto__: Person.prototype,
doWork: function(){
console.log(this.getFullName() + " is doing work");
}
}
function Manager(firstName,lastName,dob,dept){
this.firstName = firstName;
this.lastName = lastName;
this.dob = new Date(dob);
this.position = "Manager";
this.dept = dept;
}
Manager.prototype = {
constructor: Manager,
__proto__: Employee.prototype,
fireEmployee: function(emp){
emp.isFired = true;
console.log(this.getFullName() + " has fired " + emp.getFullName());
}
}
var per = new Person("Bob","Saget","1990-02-05");
var emp = new Employee("Jane","Doe","1980-05-02","Clerk","Sales");
var mgr = new Manager("Jim","Smith","1970-09-10","Sales");
Employee
继承自Person.prototype
,Manager
继承自Employee.prototype
。好又简单。
但是,我已经读过所有网络浏览器都不保证__proto__
属性,因为ES6还没有被广泛采用。我一直在扫描互联网,试图找到一个明确的解释,该怎么做,我有点迷失。
除了使用__proto__
之外,在ES5中设置原型继承链的安全,广泛支持的方法是什么?
答案 0 :(得分:1)
最安全的方法是使用标准 ES5及以上方法。
function A() {}
function B() {}
B.prototype = Object.create(A.prototype);
答案 1 :(得分:0)
引自MDN:
使用__proto__是有争议的,并且不鼓励。它最初从未包含在EcmaScript语言规范中,但现代浏览器决定实现它。直到最近,__ proto__属性已经在ECMAScript 6语言规范中针对Web浏览器进行了标准化,以确保兼容性,因此将来会得到支持。它已被弃用,有利于Object.getPrototypeOf / Reflect.getPrototypeOf和Object.setPrototypeOf / Reflect.setPrototypeOf(尽管如此,设置对象的[[Prototype]]是一个缓慢的操作,应该是如果表现是一个问题就避免了。)
请同时考虑有关表现的警告
警告:根据现代JavaScript引擎优化属性访问的性质,在每个浏览器和JavaScript引擎中,更改对象的[[Prototype]]是非常慢的操作。 (...)
如果您不介意性能影响,或者只是想尝试原型,那么文章Inheritance and the prototype chain就JS中的原型链如何工作提供了一个很好的介绍。我将在这里引用提到创建自定义原型链的三种不同方法的部分:
A"构造函数"在JavaScript中只是"只是"恰好用new operator调用的函数。
function Graph() {
this.vertices = [];
this.edges = [];
}
Graph.prototype = {
addVertex: function(v){
this.vertices.push(v);
}
};
var g = new Graph();
console.log("g:", Object.keys(g))
console.log("g.prototype:", Object.keys(Object.getPrototypeOf(g)))

Object.create
ECMAScript 5引入了一种新方法:Object.create()。调用此方法会创建一个新对象。该对象的原型是函数的第一个参数:
var a = {a: 1};
// a ---> Object.prototype ---> null
var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a); // 1 (inherited)
var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null
var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty);
// undefined, because d doesn't inherit from Object.prototype

class
关键字ECMAScript 6引入了一组实现类的新关键字。虽然这些结构看起来像基于类的语言开发人员熟悉的结构,但它们并不相同。 JavaScript仍然基于原型。新关键字包括class,constructor,static,extends和super。
"use strict";
class Polygon {
constructor(height, width) {
this.height = height;
this.width = width;
}
}
class Square extends Polygon {
constructor(sideLength) {
super(sideLength, sideLength);
}
get area() {
return this.height * this.width;
}
set sideLength(newLength) {
this.height = newLength;
this.width = newLength;
}
}
var square = new Square(2);

我同意Matias'回答并建议使用Object.create
,因为它不会隐藏JavaScript的原型性质 - 与构造函数或ES6类相比。