前端之路-了解原型和原型链

在javaScript的学习过程中,原型是我们必须搞懂的一个概念,每一个javaScript对象都有一个内置的属性 [[prototype]],他指向的是另一个对象,这个对象就是它的原型.

🐟原型

在javaScript中,使用构造函数来创建对象实例,构造函数所有的原型可以用来定义所有实例共享的属性和方法

javascript 复制代码
   person.prototype.say = function () {
    console.log('Hello');
}
  Person.prototype.age = 18

 function Person() {}
 let person1 = new Person()
 let person2 = new Person()
 console.log(person1===person2) // 输出false

通过构造函数创建出来的都是相互独立的对象,但是他们之间会拥有公共的属性他就是构造函数的原型(原型是所有实例对象的公共祖先),用过构造函数创建的实例对象,可以继承该函数原型的属性

arduino 复制代码
console.log(person1.say())  
console.log(person2.say())
// 都是输出 Hello
console.log(person1.age=person2.age)
//输出true,都是18

原型可以减少内存占用,通过原型共享属性和方法,可以避免在每个对象实例中重复存储相同的内容,从而节省内存空间。

比如说,如果张三需要购买最近最火的一辆车------小米su7,雷总支持你定制你的名字和车身的颜色,我们来定义一个Car函数

ini 复制代码
function Car(owner,color){
        this.name='su7'
        this.lang = '5000'
        this.height = '1400'
        this.owner = owner
        this.color = color
        }

张三喜欢黑色的车身,我们可以通过实例化创建这样一个对象

csharp 复制代码
let car1 = new Car('张三','black')

这时候李四看见张三买了,也想买一辆,他喜欢红色

csharp 复制代码
let car2 = new Car('李四','red')

李四和张三购买小米su7的时候,都将函数Car的代码全部走了一遍,呢就意味着这个车子的车身,结构,每次都要重新打造一遍,生产成本特别高,除了颜色和买家的姓名外,车子的结构和参数都是定死的,这样反复执行就会很浪费空间,这个时候原型就可以派上用场了

ini 复制代码
 Car.prototype.name = 'su7'
 Car.prototype.lang = 5000
 Car.prototype.height = 1400
 function Car(color, owner) {
                            //提出去降低代码的耦合度
this.color = color
this.owner = owner
}

再去创建car1然后访问他的name依旧可以访问到

arduino 复制代码
 console.log(car1.name);

这样写的好处是在批量化生产的时候,不用反复去执行构造车身的固有属性,减少浪费.

呢下面这种写法可不可以实现上述操作呢

yaml 复制代码
Car.prototype = {
    name: 'su7',
    lang: 5000,
    height: 1400
}
arduino 复制代码
 console.log(car1.name);

依旧可以输出 'su7',但是这种写法是有问题的,因为Car的原型本身就是一个对象,这个操作相当于你重新对他赋值了一个新对象,其他属性会消失.所以不能使用这个写法。

实例对象隐式具有构造函数原型身上的属性,且是只读属性

arduino 复制代码
Person.prototype.listen = '周杰伦'  //隐式具有
function Person() {
    this.name = '彭于晏'
}

let p = new Person()
p.listen = '薛之谦'    //显示具有

console.log(p.listen);   //薛之谦
console.log(Person.prototype.listen);  //周杰伦

delete p.listen
console.log(p.listen); //周杰伦 

实例对象有一个属性 constructor 很有趣 ,它可以帮助你找到他的构造函数,它可以记录自己是谁创建的

css 复制代码
访问p的constructor
console.log(p.constructor);

🐟显示原型和隐式原型

一、显示原型

对于函数对象来说,他们每个人都有一个属性,prototype,它用来实现属性和方法的继承,用函数作为构造函数创建的实例对象,新创建的实例对象的隐式原型会指向构造函数的显示原型

二、隐式原型

对每一个对象来说,他们都有一个隐式原型 __ proto__ 他是指向构造函数的prototype原型,这样对象就可以通过隐式原型去访问他的构造函数的属性和方法

显示原型和隐式原型相互结合构成了我们下面要介绍的原型链机制,它的存在可以让对象能访问他的构造函数的属性和方法.

🐟原型链

如果你能明白这张图,原型这一个知识点你就彻底通关了.

  • 对于对象f1 而言 它们是由Function Foo()实例化构造的,而Function Foo()这个函数对象的显示原型prototypeFoo prototype,所以 f1 的隐式原型 __ proto__Foo prototype,因为对对象来说,隐式原型 __ proto__ 他是指向构造函数的prototype原型
  • 对于对象o1来说,o1__proto__ 属性指向 Object.prototype。因为 o1 是由 Object 构造函数创建,而 Object 函数的 prototype 属性指向 Object.prototype
  • function Foo()他也是一个对象所以他有隐式原型,同时他作为一个函数对象,它也具有显示原型。 函数的隐式原型是创建这个函数构造的显示原型,函数是由大写的function Function()创建的,所以 他的隐式原型指向Function prototype
  • function Function()他也是一个对象,构造函数也是对象,所以它既有隐式原型也有显示原型 ,他的隐式原型直接指向他的显示原型
  • Object.prototype__proto__ 属性指向 null,这里是原型链的尽头。

最后问大家一个问题? 所有的对象都有原型吗,答案是No,Object.create(null)创建出来的对象就没有原型

Object.create()的作用就是创建一个新的对象,它可以让你指定一个原型对象,新创建的对象将会继承他的属性和方法

相关推荐
hackeroink1 小时前
【2024版】最新推荐好用的XSS漏洞扫描利用工具_xss扫描工具
前端·xss
迷雾漫步者2 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-3 小时前
验证码机制
前端·后端
燃先生._.4 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖5 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235245 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240256 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar6 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人6 小时前
前端知识补充—CSS
前端·css