网站首页 > 技术文章 正文
关注我:知码前端,获取更多前端知识~~~
前言
哇呀呀~我说寒山说哭 我带你出 我敬滴酒带你出 我欲成冰再也无退路 怎舍寒冰冰冻我心哭~~~
Hello,广大的前端小伙伴们,又到了写文章的时候,我们说一下在javascript中一个比较重要的知识点,也是一个比较难理解的知识点,可以这么说如果学javascript这门语言不学会这个知识,那只能说学的没点意思~~那我们来说一下到底要讲什么知识呢----原型
要讲原型我们得分几个点讲解一下:
- 为什么要有原型
- 原型是什么
- 原型链是什么
- __propo__、prototype、contstructor这三个属性是什么
该篇文章可能会比较长,也可能会比较难懂,希望小伙伴们耐心,多看几次,好好理解~相信大家一定会学会这个知识点。
为什么要有原型
我们知道js中对象是通过构造函数来创建是,有的小伙伴可能要开始怼了,我创建对象的时候就没有用构造函数:
// 我直接通过字面量的方法来创建一个对象,而没有构造函数
const person = {}
// 其实上面代码也可以写成下面的
const person = new Object()
// 这两个写法是等价的
那么我们通过构造函数来创建一个对象,就可以把对象的一些属性和方法直接写到函数里面:
function Person(name, age) {
this.name = name
this.age = age
}
const person = new Person('知码', 20)
console.log(person.name) // '知码'
console.log(person.age) // '知码'
这样写是没有问题的,但是会有一个缺点:用一个构造函数来创建的实例之间,无法共享属性。从而导致系统的资源浪费。我们对每个实例添加一个方法:sayHello
function Person(name, age) {
this.name = name
this.age = age
this.sayHello = function () {
console.log('hello,' + this.name)
}
}
const person1 = new Person('知码', 20)
const person2 = new Person('前端', 30)
console.log(person1.sayHello === person2.sayHello) // false
上面代码创建的两个实例都有相同的属性:name、age、sayHello。对于name和age来说是可以的,各自一份。但对于sayHello这个方法,有会浪费系统资源,因为没有必要两个实例都有这个方法。换句话说,每个实例之间应该共享这个方法。
为了解决这个问题,js就提供了原型对象(prototype)这个对象。
原型是什么
原型就是一个对象,然后用prototype这个变量来引用。每个function函数在被创建的时候都会有这个属性。(这里注意一下,只有用function声明的函数才会有这个属性,而用箭头函数是没有的。)当函数被普通调用的时候,这个对象是没有什么作用的。但当函数被当成构造函数使用的时候,这个属性就是每个实例的原型对象。在这个对象上创建的属性和方法都可以在每个实例之间共享。如:
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.address = '北京'
const person1 = new Person('知码', 20)
const person2 = new Person('前端', 30)
person1.address // '北京'
person2.address // '北京'
// 可以看出`address`这个属性可以被两个实例共享
// 如果改变了这个`address`值,那么每个对象也会改变
Person.prototype.address = '上海'
person1.address // '上海'
person2.address // '上海'
可能有的小伙伴会问了,没有在函数中定义address这个属性呀,为什么实例对象会访问到呢?
如果实例对象身上有某个属性或者方法,那么会优先调用自身的,如果在自身上没有找到,就会到原型对象上去找。
对于address我们确定是没有在函数内定义,但是在Person函数的原型上定义了,所以实例对象就会按上述规则去找,最终找到address这个属性了。
原型链是什么
上面说道原型就是一个对象,在javascript中每个对象都可以充当一个原型对象,而每个对象都有自己的原型对象。就这样:
对象---->原型对象---->原型对象上的原型对象----> ...---->Object.prototype---->null
最终会到Object上的原型对象。这就是原型链。原型链的尽头就是null
当某个对象要访问某个属性或者方法的时候,就会按这个链去找,如果自身或者从某个原型上找到了属性,就不会再继续往下查找,直接返回。如果都没有所有的原型对象都没有找到这个属性,就返回undefined。举个例子说一下:
function Person(name, age){
this.name = name
this.age = age
}
Person.prototype.address = '北京'
const person = new Person('知码', 20)
person.name // '知码'
person.address // '北京'
person.toString() // [object Object]
person.height // undefined
或许又有小伙伴要问了,对于实例对象来说,它怎么知道去原型对象上去查找自身没有的属性或者方法呢?或者说他是通过什么样的机制去查找呢?这就用到下面要说的__proro__、prototype、constructor这三者的关系了。
__propo__、prototype、contstructor这三个属性是什么
如果你能看这到里说明你对原型和原型链有一个比较客观的认识。接下来的内容可能比较难懂,再坚持一下
__proto__
__proto__是前后两个下划线_ _,不是一个整体的下划线。
当我们在创建一个对象的时候,系统都会给这个对象创建一个额外的属性__proto__,这个属性就是指向的构造函数中的原型对象。它是实例对象独有的。所以通过它就能访问到了函数原型对象。
function Person(name, age){
this.name = name
this.age = age
}
const person = new Person('知码', 20)
person.__proto__ === Person.prototype // true
//两者都是指向同一个对象
prototype
前面也提过这个属性,它是function函数独有的。指向一个对象。
constructor
这个属性是prototype对象的一个属性,也就是说每个函数原型对象默认都会有这个属性,它指向了构造函数本身。
用一个句话描述一下这三个对象之间的关系:
每个实例对象都有__proto__属性,指向着构造函数的原型对象prototype,prototype对象里面有一个属性constructor属性,指向着构造函数本身。
好了,今天先介绍这么多,下节我们细说下这三个属性。
关注我:知码前端,获取更多前端知识~~~
猜你喜欢
- 2024-11-10 这样理解 JS 原型链,通透 js原型链的理解
- 2024-11-10 JavaScript-原型链 javascript 原型,原型链 ? 有什么特点?
- 2024-11-10 javascript原型链 js原型链的用处
- 2024-11-10 js 原型/原型链/构造函数/实例/继承
- 2024-11-10 【JavaScript 高级】深入了解原型链
- 2024-11-10 快速读懂JavaScript中的原型链 js的原型和原型链是什么
- 2024-11-10 你可能不太理解的JavaScript - 原型与原型链
- 2024-11-10 我在jacascript中学习到的那些原型链,你知道吗?
- 2024-11-10 JavaScript中的原型prototype和__proto__的区别及原型链概念
- 2024-11-10 面试问题分享 - 5:解释一下 原型、构造函、实例、原型链 之间的关系
- 标签列表
-
- content-disposition (47)
- nth-child (56)
- math.pow (44)
- 原型和原型链 (63)
- canvas mdn (36)
- css @media (49)
- promise mdn (39)
- readasdataurl (52)
- if-modified-since (49)
- css ::after (50)
- border-image-slice (40)
- flex mdn (37)
- .join (41)
- function.apply (60)
- input type number (64)
- weakmap (62)
- js arguments (45)
- js delete方法 (61)
- blob type (44)
- math.max.apply (51)
- js (44)
- firefox 3 (47)
- cssbox-sizing (52)
- js删除 (49)
- js for continue (56)
- 最新留言
-