一、原型概念
- 任何对象都有一个原型,该对象可以使用原型上的属性
- 原型也是一个对象
二、如何获取对象的原型
-
从对象的角度(隐式原型)
对象.__proto__
-
从构造函数的角度(显示原型)
构造函数.prototype
注意: 通过该方式获取的不是构造函数的原型,是构造函数实例的原型。
所有的对象都具有 __ proto__ 属性
,可以获取到对象自己的原型
函数类型的对象具有 __ proto__ 属性
获取自己的原型和 prototype
获取实例的原型两个属性
三、对象、构造函数、原型之间的关系
1. 对象和构造函数
- 对象是构造函数的实例,构造函数是对象的抽象(描述)
- 一个对象只能对应一个构造函数,一个构造函数可以对应多个对象
2. 对象和原型
- 对象可以使用(继承)原型上的属性(方法)
- 一个对象只能有一个原型,原型可以作为多个对象的原型
3. 构造函数和原型
- 使用构造函数的prototype属性获取它实例的原型
- 构造函数相同的对象,原型也一样
四、自定义构造函数时原型的应用
// 定义构造函数
function User(name, age) {
// 设置属性
this.name = name;
this.age = age;
}
// 将方法添加到原型上
User.prototype.getInfo = function () {
console.log(this.name + '今年' + this.age + '岁了');
};
// 实例化 user
var u = new User('xx', 98);
u.getInfo();
// 实例化
var u1 = new User('yy', 16);
u1.getInfo()
五、判断属性是否属于对象本身
对象.hasOwnProperty('属性名')
// 自定义构造函数
function Person(name, age) {
//设置对象的属性
this.name = name;
this.age = age;
}
// 给原型添加方法
// 把方法定义到原型上,可以节省内存
Person.prototype.say = function () {
console.log(this); //谁调用了this,this就指向谁。
console.log('我是' + this.name + ',我今年' + this.age + '岁了');
};
//实例化对象
var p1 = new Person('曹操', 18);
console.log(p1.hasOwnProperty('name')); // true 自身的属性
console.log(p1.hasOwnProperty('age')); // true 自身的属性
console.log(p1.hasOwnProperty('say')); // false 原型上的属性
console.log(p1.hasOwnProperty('constructor')); // false 原型上的属性
console.log(p1.hasOwnProperty('grade')); // false 自身和原型都没有的属性
六、原型链
1. 概念
- 每个对象都有原型,原型也是对象,原型也有原型,形成了原型链
- 原型链的终点是一个顶层原型对象 Object.prototype
2. 原型链的作用
- 当使用对象中某个属性的时候,先查看对象自身有无该属性
- 如果对象本身没有该属性,查找对象的原型,如果没有继续查找原型的原型
- 一直到顶层原型对象,如果还未查找到,自动得到undefined
3. 原型链和构造函数
-
每个对象都有原型,每个对象都有构造函数,对象只会从原型上继承属性
-
Array、Object、Number等都是Function的实例,原型都是Function.prototype
Function.prototype的构造函数是Object的,Object的原型是Function.prototype
-
Function的构造函数是自己,所以
Function.__ proto __ ===Function.prototype
4. instanceof和原型链
- 该运算符判断一个对象是否是某个构造函数的实例
- 如果是对象自己的构造函数成立,如果是原型链上某个对象的构造函数也成立
[] instanceof Array; //true
[] instanceof Object; //true
5. constructor属性
对象自身所设置的constructor并不指向自己的构造函数,指向以他为原型的对象的构造函数
七、面向对象继承
1. 规则
class 父类 {}
class 子类 extends 父类 {}
2. 原型继承特点
- JS 对象依靠原型链实现继承
- 多个对象可以以同一个对象为原型; 一个对象的原型只能有一个。
- 同构构造函数的 prototype 可以获取到对象的原型
3. 实现JS中构造函数和构造函数之间继承
// 定义父类
function User(name, address) {
// 属性添加到实例本身上
this.name = name;
this.address = address;
};
// 方法添加到实例的原型上
User.prototype.addShopCart = function(product) {
console.log(this.name + '将' + product + '商品加入购物车')
}
// 定义子类 普通用户
function NormalUser(name, address, adTime) {
this.adTime = adTime;
// 将父类上定义的属性加到 NormalUser的实例上
User.call(this, name, address);
}
// 设置NormalUser的实例的原型是User的一个实例
NormalUser.prototype = new User();
// 给NormalUser的实例的原型添加 constructor 属性,指向 NormalUser(该行不会改变任何原型结构)
NormalUser.prototype.constructor = NormalUser;
// 添加方法
NormalUser.prototype.buyVip = function() {
console.log('我要购买vip');
};