继承与原型链
当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object)都有一个私有属性(称之为 _ _proto _ _) 指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(_ proto _),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。
如图:
-
js分为函数对象和普通对象,每个对象都有
__proto__属性,但是只有函数对象才有prototype属性 -
Object、Function都是js内置的函数, 类似的还有我们常用到的Array、RegExp、Date、Boolean、Number、String
显示原型 prototype
// 构造函数Foo
function Foo(name) {
this.name = name;
this.sayName = function() { alert(this.name) }
}
// 实例对象f1
let f1 = new Foo('Zaxlct');
// Foo.prototype.constructor === Foo
// true
// f1.__proto__ === Foo.prototype
// true
- 每一个构造函数(类)都拥有一个prototype属性,这个属性指向一个对象,也就是原型对象。里面存储了当前类供实例调用的属性和方法。
- 在浏览器默认给原型对象开辟的堆内存中有一个constructor属性:存储的是当前函数(类)本身(注意:自己开辟的堆内存中默认没有constructor属性,需要自己手动添加)
- 每个实例对象都有一个_ _proto _ _属性,这个属性指向当前实例所属类的原型。
- 原型对象的隐式原型等于构造函数Object的原型对象 Object.prototype.
隐式原型 __proto__
每一个对象都会有一个属性__proto__,它指向构造函数的prototype原型对象,之所以我们实例对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在。
自带的构造函数
- new Object()
- new Function()
- 所有构造函数都是new Function() 产生的,所有构造函数的隐式原型
__proto__都指向Function的原型对象
Object.__proto__ === Function.prototype
true
原型链
实例对象在查找属性与方法时,如果查找不到,就会沿着__proto__去与对象关联的原型上查找,如果还查找不到,就去找原型的原型,直至查到最顶层,这也就是原型链的概念
new关键字
new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。
constructor- 一个指定对象实例的类型的类或函数。
1、创建一个空的简单JavaScript对象(即{});
2、链接该对象(即设置该对象的构造函数)到另一个对象 ;
3、将步骤1新创建的对象作为this的上下文 ;
4、如果该函数没有返回对象,则返回this。
function Car(name){
this.name = name
}
function myNew(constructor,...rest){
let ins = {}
ins.__proto__ = constructor.prototype
let res = constructor.call(ins,...rest)
return res!==null && typeof res === 'object'? res:ins
}
let my = myNew(Car,'红旗')
console.dir(my)
instanceOf关键字
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。
语法
object instanceof constructor
参数
object某个实例对象constructor某个构造函数
描述
instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上。
function myInstanceof(obj,constructor){
if(obj === null && typeof obj !== 'object') return false
let objProto = obj.__proto__
let conPrototype = constructor.prototype
while(true){
if(objProto === null) return false
if(objProto === conPrototype) return true
objProto = objProto.__proto__
}
}
console.log(myInstanceof(my,Car)) //true
继承
重写原型对象
function Father(name){
this.name = name
}
Father.prototype.all = function all(){
console.log('父级所有')
}
function Son(age){
//构造函数继承
// Father.call(this)
this.age = age
}
Son.prototype.have = function have(){
console.log('子集所有')
}
//原型链继承
Son.prototype = new Father()
let kid = new Son(19)
console.log(kid)
//1. Son {age: 19}
//1. 1. age: 19
// 1. [[Prototype]]: Father
// 1. 1. name: undefined
// 1. [[Prototype]]: Object
// 1. 1. all: ƒ all()
// 1. constructor: ƒ Father(name)
// 1. [[Prototype]]: Object
//Object.create()
//Object.assign()