【JS】原型与原型链

77 阅读3分钟

继承与原型链

当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象(object)都有一个私有属性(称之为 _ _proto _ _) 指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(_ proto _),层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。 如图: image.png

  • 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属性,这个属性指向一个对象,也就是原型对象。里面存储了当前类供实例调用的属性和方法。

image.png

  • 在浏览器默认给原型对象开辟的堆内存中有一个constructor属性:存储的是当前函数(类)本身(注意:自己开辟的堆内存中默认没有constructor属性,需要自己手动添加)
  • 每个实例对象都有一个_ _proto _ _属性,这个属性指向当前实例所属类的原型。
  • 原型对象的隐式原型等于构造函数Object的原型对象 Object.prototype.

image.png

隐式原型 __proto__

每一个对象都会有一个属性__proto__,它指向构造函数的prototype原型对象,之所以我们实例对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型的存在。

自带的构造函数

  • new Object()
  • new Function()
  • 所有构造函数都是new Function() 产生的,所有构造函数的隐式原型__proto__都指向Function的原型对象
Object.__proto__ === Function.prototype
true

image.png

原型链

实例对象在查找属性与方法时,如果查找不到,就会沿着__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()