js-原型链

1、 函数的prototype属性

  • 每个 函数 都有一个prototype属性(是一个object类型数据),它默认指向一个object空对象(即称为:原型对象,不是真的空的,是没有我们自己定义的数据)
 console.log(typeof Date.prototype) //object
 console.log(Date.prototype) //如图1所示
 function fun(){}
 console.log(fun.prototype)   //默认指向一个object空对象(没有我们的属性)

在这里插入图片描述图1
在这里插入图片描述图2

/* Date函数的流程基本就是
     首先创建一个Date函数,
     然后通过Date.prototype(指向原型对象)向Date函数原型对象中添加很多方法
     如下:以函数fun为例
*/
 function fun(){}
 fun.prototype.test = function(){}
  console.log(fun.prototype)

在这里插入图片描述

  • 原型对象(定义函数的原型即prototype)中有一个属性constructor,他指向函数对象
// 原型对象中有一个属性constructor,他指向函数对象
console.log(Date.prototype.constructor === Date)  // true
console.log(fun.prototype.constructor === fun)  // true

2、 给原型对象添加属性(一般都是方法)

  • 作用:函数的所有实例对象自动拥有原型中的属性(方法)
/* 
给原型对象添加属性(一般都是方法)===》实例对象可以访问
*/
 function Fun(){}
 Fun.prototype.test = function(){
 console.log('test()')
}
var fun =  new Fun() // 实例化对象
fun.test() //test()  实例对象可以直接访问

3、 显式原型与隐式原型

  • 每个函数function都有一个prototype,即显式原型
  • 每个实例对象都有一个__proto__,即隐式原型
  • 对象的隐式原型的值为其对应的构造函数的显式原型的值
/* 
每个**函数function**都有一个prototype,即显式原型,默认指向一个object空对象(不是真的空的,是没有我们自己定义的数据)
*/
function Fn(){     //内部语句:this.prototype = {}
}
console.log(Fn.prototype)
/* 
每个**实例对象**都有一个__proto__,即隐式原型,默认指向一个object空对象
*/
var fn =  new Fn() // 实例化对象,内部语句:this.__proto__ =  Fn.prototype
console.log(fn.__proto__)

/* 
对象的隐式原型的值为其对应的构造函数的显式原型的值,引用地址值相同,指向同一个对象
*/
console.log(Fn.prototype === fn.__proto__)   //true


Fn.prototype.test = function(){
console.log('test()')
}
fn.test()   // test()   对象可以直接访问自己__proto__里面的属性和方法,本质上 对象的__proto__与其构造函数的prototype 指向的是同一个对象

在这里插入图片描述

  • 内存结构
    在这里插入图片描述
  • 总结:
    (1)对象的prototype属性:在定义函数时自动添加的,默认值是一个空object对象(不是真的空的,是没有我们自己定义的数据)
    (2)对象的__proto__属性:创建对象时自动添加的,默认值是构造函数的prototype属性值
    (3)程序员可直接操作显式原型,但不能操作隐式原型(es6之前)

4、 原型链

  • 访问一个对象的属性时,先在自身属性中查找,找到返回
  • 如果没有,再沿着_proto_这条链向上查找。找到返回
  • 如果最终没有找到,返回undefined
  • 别名: 原型链本质上是隐式原型链,故别名叫隐式原型链
  • 作用:查找对象的属性(方法)
 console.log(fn.test3) //undefined
 console.log(fn.test3())   //fn.test3()有这个()表示在执行,会报错说没有定义声明这个test3这个方法

在这里插入图片描述
在这里插入图片描述

  • 函数的显式原型指向的对象:默认是空的实例对象(但Object不满足)
var fn =  new Fn()
console.log(Fn.prototype instanceof Object) //true
console.log(Object.prototype instanceof Object) //false
console.log(Function.prototype instanceof Object) //true
  • 所有函数都是Function的实例(包含Function)
//所有函数都是Functionde的实例对象,故有隐式原型属性
 console.log(Function.__proto__ === Function.prototype) //true
  • Object的原型对象是原型链的尽头
//所有函数都是Functionde的实例对象,故有隐式原型属性
console.log(Object.prototype .__proto__ ) //null

5、 原型链-属性问题

  • 读取对象的属性值时:会自动到原型链中查找(先在自身属性中找,没有的话就去原型链中找)
  • 设置对象的属性值时:不回查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值
function Fn(){}
Fn.prototype.a = 'xxx'
var fn1 =  new Fn()
console.log(fn1 .a,fn1) //xxx
var fn2 =  new Fn()
fn2.a = 'yyy'
console.log(fn1.a,fn2.a,fn2) //xxx yyy

在这里插入图片描述
在这里插入图片描述

  • 方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
// 属性一般通过构造函数定义在对象本身上,不通过prototype设置,不定义在原型上
function Person(name.age){
 this.name = name
 this.age = age
}
// 方法一般定义在原型中
Person.prototype.setName(name){
   this.name = name
}
var persion=  new Person(‘tom’,12)
persion.setName('Bob')
console.log(persion.name,persion.age) //Bob 12
 var persion2=  new Person(‘tom’,13)
persion2.setName('Cat')
console.log(persion2.name,persion2.age) // Cat 13
  • 每个对象都有自己的属性 persion,persion2,对象的方法放在原型中
    在这里插入图片描述
  • 实例对象的隐式原型(proto)与构造函数的显式原型指向同一个对象,所以persion与persion1的__proto__属性是相同的,因为他们的构造函数都是Persion
// 属性一般通过构造函数定义在对象本身上,不通过prototype设置,不定义在原型上
function Person(name.age){
 this.name = name
 this.age = age
}
// 方法一般定义在原型中
Person.prototype.setName(name){
   this.name = name
}
var persion=  new Person(‘tom’,12)
persion.setName('Bob')
console.log(persion.name,persion.age) //Bob 12
 var persion2=  new Person(‘tom’,13)
persion2.setName('Cat')
console.log(persion2.name,persion2.age) // Cat 13
console.log(persion.__proto__ === persion2.__proto__) //true

6、 A instanceof B------判断A是否为B的实例

  • instanceof是如何判断的
    *表达式:A instanceof B
    *如果B函数的显示原型对象在A对象的原型链上,返回true,否则返回false
    *如下图// Foo.prototype有__proto__说明是个实例对象,即函数的原型对象默认是空的Object实例对象
function Foo(){}
var f1 = new Foo()
console.log(f1 instanceof Foo,f1 instanceof Object ,) // true,true
// Foo.prototype有__proto__说明是个实例对象,即函数的原型对象默认是空的Object实例对象

在这里插入图片描述

  • Function是通过new自己产生的实例
//注:Object =  new Function(),Object是函数
console.log(Object instanceof Function) // true
console.log(Object instanceof Object ) // true
console.log(Functioninstanceof Function) // true
console.log(Function instanceof Object ) // true
function Foo(){}
console.log(Object instanceof Foo) // false

(Object instanceof Function) // true
在这里插入图片描述
(Object instanceof Object ) // true -------- 所有函数的原型对象都是空的Object的实例:Function.prototype.proto = Object.prototype(Object除外)
在这里插入图片描述
(Functioninstanceof Function) // true -------- Function是通过new自己产生的实例
在这里插入图片描述
(Function instanceof Object ) // true
在这里插入图片描述
(Object instanceof Foo) // false
在这里插入图片描述
(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()  // a()
f.b()  //报错 not a function
console.log(f ) 
console.log(Object.prototype) 

//f.a()------------------------ a()
在这里插入图片描述
//f.b()------------------------ 报错
在这里插入图片描述
//f.b()------------------------ 报错原因,到不了Function.prototype,找不到Function.prototype.b
在这里插入图片描述

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

在这里插入图片描述
F.a() // a()
F.b() // b()
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
JavaScript中,每个对象都有一个隐藏的 `__proto__` 属性,它指向该对象的原型。原型是一个普通的对象,它包含了共享属性和方法。当我们访问一个对象的属性或方法时,JavaScript引擎会首先在该对象本身查找,如果找不到,则会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的顶端(Object.prototype)。这个原型链的过程就是通过 `__proto__` 属性来实现的。 例如,当我们创建一个实例对象 `teacher` 时,如果 `teacher` 对象本身没有 `teach()` 方法,JavaScript引擎会通过对象的 `__proto__` 属性查找到 `Teacher.prototype` 的显式原型上,如果 `Teacher.prototype` 仍然没有该方法,它会继续沿着 `Teacher.prototype.__proto__` 找到 `Person.prototype`,直到找到 `teach()` 方法并执行。这样就形成了一个原型链。 同时,可以注意到 `Object.prototype.__proto__` 的值为 `null`,即 `Object.prototype` 没有原型。所以在原型链中,当找到顶层原型还没有属性时,就会返回 `undefined`。 需要注意的是, `__proto__` 是一个非标准的属性,实际开发中不应该直接使用它。它只是内部指向原型对象 `prototype` 的一个指示器,我们应该使用 `Object.getPrototypeOf()` 或 `Object.setPrototypeOf()` 来访问和设置对象的原型。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [JS:原型和原型链](https://blog.csdn.net/elevenhope/article/details/122882582)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [JavaScript原型链(重要)](https://blog.csdn.net/liyuchenii/article/details/125957625)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值