文章目录
一.原型链机制
1. 原型链的本质
只要是对象,一定有原型对象(除原型链终点外),就是说只要这个东西是个对象,那么一定有__proto__
属性。
原型链的终点Object.prototype , 该对象没有原型对象
function People() {
}
var obj = new People()
console.log(obj.__proto__) // People {}
console.log(obj.__proto__.__proto__) // {}
console.log(obj.__proto__.__proto__.__proto__) // null
Object是一个函数,是系统内置的构造函数,用于创造对象的。Object.prototype是所有对象的原型链终点。
所以,当我们在一个对象上打点调用某个方法的时候,系统会沿着原型链去寻找它的定义,一直找到Object.prototype。
Object.prototype是所有对象原型链的终点
Object.prototype是所有对象的原型链的终点,所以我们直接给Object.prototype增加一个方法,那么世界上所有的对象都能调用这个方法:
2. 引用类型的构造函数
所有的引用类型值,都有内置构造函数。比如
new Object()
new Array()
new Function()
new RegExp()
new Date()
// 现在是一个数组字面量
var arr = [66,4343,23];
// arr.haha = 23;
// console.log(arr.haha); //23
console.log(arr.__proto__); // 不用管,直接看constructor
console.log(arr.__proto__.constructor);
// 寻找原型链的终点,发现是Object.prototype
console.log(arr.__proto__.__proto__.constructor)
3. 基本类型的包装类
基本类型值,也有包装类型。所谓包装类型,就是它的构造函数。
new Number()
new String()
new Boolean()
二. 对象与属性
判断属性是否存在
1. 对象直接打点验证某个属性是否存在
对象打点调用属性,我们之前的课程已经讲过,遍历原型链。所以就可以看出来属性是否在自己身上或原型链上。如果在,就返回值;如果不在就返回undefined.
4. instanceof 运算符
A instaceof B
验证A对象的原型链上有没有对象是通过构造函数B, new出来的对象
三. 继承
1. 原型链继承
将父类的实例作为子类的原型
// 父类型
function Supper() {
this.superProp = 'super property'
}
Supper.prototype.showSupperProp = function () {
console.log(this.superProp)
};
// 子类型
function Sub() {
this.subProp = 'sub property'
}
// 子类型的原型为父类型的一个实例对象
Sub.prototype = new Supper();
// 子类型调用父类型的方法
new Sub().showSupperProp();
2. 构造函数继承
使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
function People(name){
this.name = name;
}
People.prototype.sayHello = function(){
alert("你好我是" + this.name);
}
function Student(name,xuehao){
// 核心语句call 修改this指向
// 继承父类的name属性
People.call(this, name);
this.xuehao = xuehao;
}
Student.prototype.study = function(){
alert("好好学习,天天向上");
}
var xiaohong = new Student("小红",1001);
方法都在构造函数中定义, 只能继承父类的实例属性和方法,不能继承原型属性/方法,无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
3. 组合继承
就是将原型链继承和构造函数继承组合在一起;继承两个优点
通过调用父类构造,继承父类的属性并保留传参的优点,
然后再通过将父类实例作为子类原型,实现函数复用
function People(name){
this.name = name;
}
People.prototype.sayHello = function(){
alert("你好我是" + this.name);
}
function Student(name,xuehao){
People.call(this,name);
this.xuehao = xuehao;
}
//核心语句,继承的实现全靠这条语句了:
Student.prototype = new People('大明');
Student.prototype.study = function(){
alert("好好学习,天天向上");
}
var xiaohong = new Student("小红",1001);
xiaohong.sayHello();
调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)