简谈原型与原型链

1.jpg

记得刚学前端那会,一个面试的问我,知不知道原型与原型链,然后就懵了,回来才发现就是<code>python</code>的继承那块知识。

数据结构

说到这个先说下数据类型。

基本数据类型(值类型) (作为一般数据存在内存中)

  • String
  • Number
  • boolean
  • undefined
  • null (初始赋值 ,表示要赋值为对象,结束赋值,让变量变为一个垃圾对象回收,切断内存联系)

对象类型(引用类型) (作为地址数据存在内存中)

  • Object
  • Function
  • Array

原型

  1. 函数的prototype属性(显式原型属性)
    每个函数都有一个prototype属性,默认指向一个空对象(即叫做:原型对象)
    原型对象中有一个constructor,它指向函数对象
  2. 给原型对象添加属性(一般是方法)
    作用:函数的所有实例对象自动拥有原型中的属性(方法)
  3. 每个实例对象都有一个proto,称为隐式原型(属性),对象隐式原型的值等于构造函数显示原型的值
//构造一个函数Fn
function Fn(){
//构造时 this.proptype={}
}
console.log(Fn.prototype) // Fn有一个prototype属性指向一个原型对象
console.log(Fn.prototype.constructor ===Fn) //原型对象中有一个constructor,它指向函数对象
Fn.prototype.test=()=>"我是Fn的test方法" //给原型对象添加属性(一般是方法)
//创建一个Fn的实例对象
var fn=new Fn()  //new做了什么事情? this.__proto__=Fn.prototype
console.log(fn.__proto__===Fn.prototype) //true 对象隐式原型的值等于构造函数显示原型的值
console.log(fn.test())  // "我是Fn的test方法" 函数的所有实例对象自动拥有原型中的属性(方法)

上述代码的图解
显然对象找属性会从自身找起,之后顺着隐式原型属性proto绿色链条开始一直找,一直找到Object的原型对象

20200509 231539.jpg

还是网上的图比较直观


yuanxlian.jpg

此图关键点:
关键点一:所有函数都是Function的实例对象,Function这个构造函数也由Function自己产生Function=new Function(),所以Function的隐式原型属性等于其显示原型属性

console.log(Function.__proto__===Function.prototype) //true

关键点二:函数的显示原型指向的对象默认是空Object的实例对象(Object除外)

console.log(Fn.prototype instanceof Object) //true
console.log(Object.prototype instanceof Object) //false
console.log(Function.prototype instanceof Object) //true

关键点三:
Object的原型对象是原型链尽头

console.log(Object.prototype.__proto__)  //null

总结:

  1. 构造函数Foo,Object,Function都是由Function这个函数产生的,所以他们的隐式属性proto都先等于Function.prototype,Function.prototype是Function自己的实例对象,Function.prototype.proto最终指向一个空Object的实例对象(参考关键点二)
  2. 对象隐式原型的值等于构造函数显示原型的值
  3. 构造函数Foo,Object,Function都会产生自己得显示属性,他们的显示属性最终会指向Object

运用,探秘instanceof

数据类型判断
typeof 和 instanceof

typeof:
可以判断:undefined/数值/字符串/布尔值/function
不能判断:null,Object,array

instance of
表达式 A instanceof B (理解:A是否是B的实例,所以B的实例就是B.prototype)
如果B函数的显示原型(prototype)对象在A对象的原型链上 返回true,否则返回false

var b1={
    b2:[1,2,3],
    b3:function(){
        console.log("b2函数")
    }
}
var a = new Number(1)
function Fn(){
//构造时 this.proptype={}
}
var fn=new Fn()
console.log(typeof a )//object
console.log(typeof 1 ) //number
console.log(typeof [1,2,3]) //object
console.log(typeof null)  //object
console.log(typeof b1)  //object
console.log(typeof b1.b2) //object
console.log(typeof b1.b3) //function
console.log(typeof undefined) //undefined

console.log( 1 instanceof Object ) //false instanceof判断一个对象是否是另一个对象的实例,而数字1是基本数据类型,不是对象,
console.log( [1,2,3] instanceof Array ) //true
console.log( [1,2,3] instanceof Object ) //true
console.log( fn instanceof Function ) //Fn是构造函数生成的对象 所以Fn是一个函数对象,就像[1,2,3] 是 Array对象一样, [1,2,3] 也是 Object
console.log( fn instanceof Object )   //所以函数也是对象 函数一种特殊的对象
console.log( typeof Function) //function
console.log( typeof String )  //function
console.log( typeof Number)   //function
console.log( typeof Object )  //function
console.log( typeof Array)    //function都是构造函数

//数据类型判断
console.log( Object instanceof Function)  //true Object是一个构造函数 是New Function产生的 所以Object实例对象的__proto__指向构造函数Function的prototype
console.log( Function instanceof Object) //true 
console.log( Object instanceof Object) //true Object是一个构造函数 是New Function产生的 所以Object实例对象的__proto__指向构造函数Function的prototype  Function的prototype实例对象的__proto__指向一个空的Object对象
console.log( Array instanceof Object)  //true 构造函数也是对象

小练习

function A(){
}
A.prototype.n=1
var b =new A()
A.prototype={
  n:2,
  m:3
}
var c=new A()
console.log(b.n,b.m,c.n,c.m) //1,undefined,2,3

function F(){}
Object.prototype.a=function(){
  console.log('a()')
}
Function.prototype.b=function(){
  console.log("b()")
}
var f= new F()
f.a()
f.b()
F.a()
F.b()

文章同步我的博客

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容