原型与原型链

一、原型:prototype

1.什么是原型?

javascript常被描述为一种基于原型的语言(每个对象都拥有一个原型对象)

当访问一个对象的属性时,它不仅在该对象上寻找,还会寻找该对象的原型,以及该对象原型的原型,层层向上,直到找到或者到达原型链的末尾

函数可以有属性,每个函数都有一个特殊的属性叫做原型prototype

javascript 复制代码
function Fn(){}
console.log( Fn.prototype );

// 控制台输出

/* {
    constructor: ƒ Fn(),
    __proto__: {
        constructor: ƒ Object(),
        hasOwnProperty: ƒ hasOwnProperty(),
        isPrototypeOf: ƒ isPrototypeOf(),
        propertyIsEnumerable: ƒ propertyIsEnumerable(),
        toLocaleString: ƒ toLocaleString(),
        toString: ƒ toString(),
        valueOf: ƒ valueOf()
    }
}
*/

上面的这个对象,就是大家常说的原型对象

可以看到,原型对象有一个自有属性constructor,这个属性指向该函数,如下图关系展示

2.函数的prototype属性

每个函数都有一个prototype属性,它默认指向一个Object对象(即为:原型对象)

原型对象中有一个属性constructor,它指向函数对象

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

作用:函数的所有实例对象自动拥有原型中的属性

4.原型对象有一个属性constructor,它指向函数对象

二、显示原型与隐式原型

1.每个函数function都有一个prototype,即显示原型(属性)

2.每个实例对象都有一个_proto_,可称为隐式原型(属性)

3.对象的隐式原型的值为其对应构造函数的显示原型的值

4.内存结构

javascript 复制代码
//定义构造函数
Function Fn(){  //内部语句:this.prototype={}

}
//每个函数function都有一个prototype,即显示原型属性,默认指向一个空的Object对象
console.log(Fn.prototype)
//创建实例对象
//每个实例对象都有一个_proto_,可称为隐式原型
var fn=new Fn()//内部语句:this._proto_===Fn.prototype
console.log(fn._proto_)
//对象的隐式原型的值为其对应构造函数的显示原型的值
console.loG(fn._proto_===Fn.prototype)
//给原型添加方法
Fn.prototype.test=function(){
   console.log('test()')
}
//通过实例调用原型的方法
fn.test()

5.总结:

函数的prototype属性:在定义函数时自动添加的,默认值是一个空Object对象

对象的_proto_属性:创建对象时自动添加的,默认值为构造函数的prototype属性值

程序员能直接操作显示原型,但不能直接操作隐式原型(ES6之前)

三、原型链

1.原型链的概念?:

原型对象也可能拥有原型,并从中继承方法和属性,一层一层,依次类推。这种关系就形成了原型链(这也就是为何一个对象会拥有定义在其他对象中的属性和方法)

在对象实例和他的构造器之间建立一个连接(它是_proto_属性,是从构造函数的prototype属性派生的),之后通过溯原型链,在构造器中找到这些属性和方法

2.原型链:访问一个对象的属性时

(1)先在自身属性中查找,找到返回

(2) 如果没有,则再沿着_proto_这条链向上查找,找到返回

(3) 如果最终没有找到,返回undefined

别名:隐式原型链

作用:查找对象的属性(方法)

javascript 复制代码
function Fn(){
   this.test1=function(){
     console.log('test1()')
   }
}
Fn.prototype.test2=function(){
   console.log('test2()')
}
var fn=new Fn()
fn.test1()
fn.test2()
console.log(fn.toString())

3.构造函数/原型/实例对象的关系

(1) 函数的显示原型指向的对象默认是空的Object对象(但Object不满足)

(2)所有的函数都是Function的实例(包含Function)

(3)Object的原型对象是原型链尽头

(4)实例对象的隐式原型等于构造函数的显示原型属性,任何函数都是new Function产生的

小结:

javascript 复制代码
function Person(name) {
    this.name = name
    this.age = 20
    this.sayName = function() {
        console.log(this.name)
    }
}
//	创建实例
let person = new Person('CSDN')

(1)__proto__作为不同对象之间的桥梁,用来指向创建它的构造函数的原型对象

(2)每个对象的__proto__都是指向它的构造函数的原型对象的prototype的

javascript 复制代码
person1.__proto__ === Person.prototype

(3)构造函数是一个函数对象,都是通过Function构造器产生的

javascript 复制代码
Person.__proto__===Function.prototype

(4)原型对象本身是一个普通对象,而普通对象的构造函数都是Object

javascript 复制代码
Person.prototype.__proto===Object.prototype

(5)刚刚上面说了,所有的构造器都是函数对象,函数对象都是Function构造产生的

javascript 复制代码
Object.__proto===Function.prototype

(6)Object的原型对象也有__proto__属性指向null,null是原型链的顶端

javascript 复制代码
Object.prototype.__proto__ === null

tip:

  • 一切对象都是继承自Object对象,Object对象直接继承根源对象null
  • 一切的函数对象(包括Object对象),都是继承自Function对象
  • Object对象直接继承自Function对象
  • Function对象的__proto__会指向自己的原型对象,最终还是继承自Object对象

4.原型继承:

(1)构造函数的实例对象自动拥有构造函数原型对象的属性

(2) 利用的就是原型链、

5.原型属性问题

(1)读取对象的属性值时,会自动到原型链中查找

(2)设置对象的属性值时,不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值

(3)方法一般定义在原型中,属性一般通过构造函数定义在对象本身上

6.探索instanceof

(1)instanceof是如何判断的?

表达式:B instanceof A

如果A函数的显示原型对象在B对象的原型链上,返回trur,否则返回false

(2)Function是通过new自己产生的实例

相关推荐
卸任2 小时前
Vibe coding工具使用心得
前端·ai编程
brien93 小时前
为什么模型标称 1M,Google Antigravity 聊到 256K 却突然失忆?我们给它做了个原生行内监控圆环
前端
修炼的dance3 小时前
录屏关键帧间隔多少合适?六档实测,2秒到10秒小了75.6%
前端
Lank_M3 小时前
关键帧从1秒拉到10秒,录屏小87.3%,摄像头小10.8%
前端
补码缩写3 小时前
用 ffprobe 拆录屏,八成字节在 29 个关键帧上
前端
百思不得小李4 小时前
一个复杂的动态表单是如何实现的
前端·设计模式
陈随易4 小时前
Cmder 停更 17 个月,2.0 支持 Windows Terminal
前端·后端·程序员
清晨Coding4 小时前
删了 Cookie 还能自动登录?Google系网站登录态自动恢复的原理分析
javascript
风骏时光牛马4 小时前
前沿视界
前端
kyriewen4 小时前
我扫了 814 个依赖,97 个还敢要 Node 10
前端·javascript·程序员