-
JavaScript 中,每个实例对象( object )都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype )。
-
该原型对象也有一个自己的原型对象( proto ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
-
几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
构造函数实例
// 构造函数 Person()
function Person(name) {
this.name = name; // 这里 name 是实例属性
}
Person.prototype.name = 'cedric'; // 这里 name 是原型属性
Person.prototype.age = '18'; // 这里 age 是原型属性
Object.prototype.address = 'shanghai';
// 创建一个Person的实例
var person1 = new Person('tom');
person1.name; // tom, 获取实例对象的属性时,如果在实例属性上存在,就直接读取,此时不管原型属性上是否还有相同的属性,这就是属性屏蔽
person1.age; // 18, 没有age的实例属性,所以就去实例的原型上找到age
person1.address; // shanghai, person1的原型Person上也没有找到 address, 所以就去Person的原型Object上面去找到address
person1.sex; // undefined, person1的原型Person上也没有找到 sex, 所以就去Person的原型Object上面去, 也没找到sex
person1.hasOwnProperty('name'); // true
原型链
JavaScript 中,每个实例对象( object )都有一个私有属性(称之为 proto )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( proto ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
几乎所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
person1 ----> Person.prototype ----> Object.prototype ----> null
person1.__proto__ === Person.prototype; // true, person1 的原型是:Person.prototype 对象
Person.prototype.__proto__ === Object.prototype; // true, Person.prototype 的原型是: Object.prototype 对象
constructor
用 new Person() 创建的对象还从 Person 原型上获得了一个 constructor
属性,它指向函数 Person 本身
Person.prototype.constructor === Person; // true
person1.constructor === Person; // true
person1.constructor === Person.prototype.constructor; // true
Object.getPrototypeOf()
Object.getPrototypeOf这个方法返回 proto 的值,可以获取到一个对象的原型
Object.getPrototypeOf(person1) === person1.__proto__; // true
Object.getPrototypeOf(person1) === Person.prototype; // true
hasOwnProperty
方法hasOwnProperty, 判断一个属性是否为实例属性属性
person1.hasOwnProperty('name'); // true
person1.hasOwnProperty('age'); // fasle
instanceof
instanceof 可以判断一个实例是否属于某构造函数
person1 instanceof Person; // true
isPrototypeOf
isPrototypeOf()方法可以判断一个对象是否是另一个对象的原型
Person.prototype.isPrototypeOf(person1); // true
ES6 类
class Person {
constructor(name) {
this.name = name;
}
hello() {
alert('Hello, ' + this.name + '!');
}
}
// Student 需要name和grade两个参数,需要通过super(name)来调用父类的构造函数,否则父类的name属性无法正常初始化。
// Student 已经自动获得了父类 Student 的 hello 方法,我们又在子类中定义了新的 myGrade 方法。
class Student extends Person {
constructor(name, grade) {
super(name);
this.grade = grade;
}
myGrade() {
console.log('Grade is ', this.grade);
}
}