温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

javaScript 中原型与原型链是什么

发布时间:2020-10-24 14:55:26 来源:亿速云 阅读:187 作者:小新 栏目:web开发

javaScript 中原型与原型链是什么?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧!

javascript栏目简单明了介绍原型与原型链。

在 JavaScript 中,原型和原型链是不可避免的重要概念,那么怎么去理解原型和原型链呢?下面是我对原型和原型链的理解和总结。也许有些理解还比较浅薄,随着时间的推移和理解的深入,以后还会补充。如果大家发现我理解的有问题,欢迎大家在评论中指正。

1. 为什么 javaScript 设计为基于原型的模式

在以往的学习过程中,我们曾通过学习面向对象语言 java 了解到其有三个要素:封装、继承、多态。关于继承,java 与 javascript 其实两者并不完全一样。
      那么 javascript 到底是如何设计出来的呢?早期,浏览器只能浏览网页内容,而不能进行用户交互,也就说当我们输入账号密码进行登录时,浏览器不能对其输入内容进行判断,需要通过服务器进行判断,而网景公司为了解决这一问题,发明一种与 java 搭配使用的辅助脚本语言,并在语法上有些类似。由此可以看出,javascript 受到 java 的影响,其都是对象类型,有对象则就会涉及到继承机制,那么JS的继承机制是怎么样呢?
      JS参考java的设计,使用new操作符生成对象,但其与java不同的是new后面跟的是 Construtor 而不是 Class 。

// java 中生成一个对象
Person p = new Person() // Person 指的是类名

// js 生成一个对象
function Person (age) {
    this.age = age
    this.nation = 'China'
}
var father = new Person(42) // Person 指的是构造函数
var mingming = new Person(11)复制代码

2. 构造函数 Constructor

构造函数也是普通函数,其也有 prototype 属性,与普通函数的区别是其要求首字母大写。若构造函数使用new操作符调用时,其需要执行四个步骤:
      1. 创建一个新的对象
      2. 将 this 指向这个新的对象
      3. 执行构造函数,给新对象添加属性和方法
      4. 返回这个新对象

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')复制代码

3. 原型 prototype

任何一个函数都有一个 prototype 属性,它指向 prototype 对象。那么原型其实就是一个对象,在原型上定义的属性,通过继承(new 操作符实现),实例化的对象也拥有了该属性。
      原型与构造函数的关系:构造函数内有一个 prototype 属性,通过该属性可以访问到原型。

javaScript 中原型与原型链是什么

以构造函数中的代码为例,Food 就是构造函数,Food.prototype 就是原型,food 就是参照 Food.prototype 生成的一个对象。

javaScript 中原型与原型链是什么

4. 实例 instance

实例是指一个构造函数在原型上创建可以"继承"的属性和方法,并通过new操作符创建的对象。

javaScript 中原型与原型链是什么

简单来说,我们使用 new 操作符创建一个 food 实例,并且可以通过 instanceof 检验实例与构造函数之间的关系。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 实例化
var res = food instanceof Food // 检查 food 是否为 Food 实例
console.log(res) // true复制代码

当我们在原型上定义一个属性时,实例也会"继承"这个属性。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 实例化
var res = food instanceof Food // 检查 food 是否为 Food 实例
console.log(res) // true

// 原型定义属性
Food.prototype.type = 'object named Food'
var foodRes = food.type // 实例继承的属性
console.log(foodRes) // object named Food复制代码

5. 隐式原型 __proto__

任何对象在创建时都会有一个 __proto__ 属性,它指向产生当前对象的构造函数的原型对象。由于该属性并非标准规定的属性,所以不要随便去更改该属性的值,以免破坏原型链。也就是说,实例可以通过 __proto__ 属性访问到原型。

javaScript 中原型与原型链是什么

对象中的 __proto__ 属性在所有实现中是无法访问到的,但是可以通过 isPrototypeOf() 方法来确定对象之间是否存在着这种关系。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 实例化
console.log(food.__proto__ === Food.prototype) // true
console.log(Food.prototype.isPrototypeOf(food)) // true复制代码

6. 构造函数 constructor

构造函数可以通过 prototype 属性访问到原型,那么原型也是能够通过某种途径访问到构造函数的,其就是原型中的一个属性 constructor ,该属性并不是真正的构造函数,真正的构造函数是指 Constructor,两者不要混淆了。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')
console.log(Food.prototype.constructor === Food) //true复制代码

javaScript 中原型与原型链是什么

关键:prototype 的 constructor 指向构造函数本身    

那么构造函数、原型、实例三者的关系应该是这样的:

javaScript 中原型与原型链是什么

为了更好地理解这一过程,我通过一个故事给大家梳理一下:
      1. 很久以前,有个雕刻家偶然看到一个很精致的花瓶(原型 Food.prototype)
      2. 一天,他想通过大批生产复刻这个花瓶来发家致富,于是他先分析这个花瓶,还原了雕刻的过程,并设计出了一条生产线(构造器 Food)
      3. 然后通过这条生产线,雕刻出许许多多的复刻花瓶。(实例 food)

7. 原型链

proto 是任何对象都有的属性,在js中会形成一条 proto 连接起来的链条,递归访问 proto 直到值为 null ,这个搜索过程形成的链状关系就是原型链。

function Food (name) {
    this.name = name
    this.eat = function () {
        console.log('eat')
    }
}
var food = new Food('banana')  // 实例化
// 原型链
console.log(food.__proto__) // Food {}
console.log(food.__proto__.__proto__) // {}
console.log(food.__proto__.__proto__.__proto__) // null复制代码

如下图:

javaScript 中原型与原型链是什么

总结

1. 每创建一个函数都会有一个 prototype 属性,该属性是一个指针,指向一个对象,该对象为原型对象(Food.prototype)。
      2. 原型对象上的默认属性 constructor 也是一个指针,指向其相关的构造函数。
      3. 通过 new 操作符产生的实例对象都会有一个内部属性指向原型对象,该实例对象可以访问原型对象上的所有属性和方法。
      4. 实例可以通过内部指针访问到原型对象,原型对象也可以通过 constructor 找到构造函数。
      5. 每个构造函数都有一个原型对象,原型对象上包含一个指向构造函数的指针,实例包含一个指向原型对象的内部指针。
      6. __proto___ 的指向取决于对象创建时的实现方式。
      7. 构造函数实例,封装的函数,如果通过 new 操作符来调用则是构造函数,否则则不是。           8. 在整个原型链上寻找某个属性,对性能有影响,越是上层的原型对象,对性能的影响越大。
      9. js中一切皆对象,通过 new Function 的是函数对象,其构造函数是 Function,而普通对象的构造函数则是 Object 。
      10. 每一个对象都有 __proto__ 属性,而每一个函数对象才有 prototype 属性。

感谢各位的阅读!看完上述内容,你们对javaScript 中原型与原型链是什么大概了解了吗?希望文章内容对大家有所帮助。如果想了解更多相关文章内容,欢迎关注亿速云行业资讯频道。

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI