JS面试高频题 原型与原型链

原型与原型链作为前端高频面试题之一,相信很多小伙伴都有遇到过这个问题。那么你是否清楚完整的了解它呢?

【相关推荐:前端面试题】

国际惯例,让我们先抛出问题:

什么是原型、原型链它们有什么特点它们能做什么怎么确定它们的关系

或许你已经有答案,或许你开始有点疑惑,无论是 get 新技能或是简单的温习一次,让我们一起去探究一番吧

如果文章中有出现纰漏、错误之处,还请看到的小伙伴多多指教,先行谢过

原型

JavaScript 是基于原型的我们创建的每个函数都有一个 prototype(原型) 属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。

简单来说,就是当我们创建一个函数的时候,系统就会自动分配一个 prototype属性,可以用来存储可以让所有实例共享的属性和方法

用一张图来表示就更加清晰了:

1.jpg

图解:

每一个构造函数都拥有一个 prototype 属性,这个属性指向一个对象,也就是原型对象原型对象默认拥有一个 constructor 属性,指向指向它的那个构造函数每个对象都拥有一个隐藏的属性 __proto__,指向它的原型对象

function Person(){}var p = new Person();p.__proto__ === Person.prototype // truePerson.prototype.constructor === Person // true

登录后复制

那么,原型对象都有哪些特点呢

原型特点

function Person(){}Person.prototype.name = 'tt';Person.prototype.age = 18;Person.prototype.sayHi = function() {    alert('Hi');}var person1 = new Person();var person2 = new Person();person1.name = 'oo';person1.name // ooperson1.age // 18perosn1.sayHi() // Hiperson2.age // 18person2.sayHi() // Hi

登录后复制

从这段代码我们不难看出:

实例可以共享原型上面的属性和方法实例自身的属性会屏蔽原型上面的同名属性,实例上面没有的属性会去原型上面找

既然原型也是对象,那我们可不可以重写这个对象呢?答案是肯定的

function Person() {}Person.prototype = {    name: 'tt',    age: 18,    sayHi() {        console.log('Hi');    }}var p = new Person()

登录后复制

只是当我们在重写原型链的时候需要注意以下的问题:

function Person(){}var p = new Person();Person.prototype = {    name: 'tt',    age: 18}Person.prototype.constructor === Person // falsep.name // undefined

登录后复制

一图胜过千言万语

2.jpg

在已经创建了实例的情况下重写原型,会切断现有实例与新原型之间的联系重写原型对象,会导致原型对象的 constructor 属性指向 Object ,导致原型链关系混乱,所以我们应该在重写原型对象的时候指定 constructor( instanceof 仍然会返回正确的值)

Person.prototype = {    constructor: Person}

登录后复制

注意:以这种方式重设 constructor 属性会导致它的 Enumerable 特性被设置成 true(默认为false)

既然现在我们知道了什么是 prototype(原型)以及它的特点,那么原型链又是什么呢?

原型链

JavaScript 中所有的对象都是由它的原型对象继承而来。而原型对象自身也是一个对象,它也有自己的原型对象,这样层层上溯,就形成了一个类似链表的结构,这就是原型链

同样的,我们使用一张图来描述

3.png

所有原型链的终点都是 Object 函数的 prototype 属性Objec.prototype 指向的原型对象同样拥有原型,不过它的原型是 null ,而 null 则没有原型

清楚了原型链的概念,我们就能更清楚地知道属性的查找规则,比如前面的 p 实例属性.如果自身和原型链上都不存在这个属性,那么属性最终的值就是 undefined ,如果是方法就会抛出错误

class类

ES6 提供了 Class(类) 这个概念,作为对象的模板,通过 class 关键字,可以定义类

为什么会提到 class :

ES6 的 class 可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已

class Point {  constructor(x, y) {    this.x = x;    this.y = y;  }  toString() {    return '(' + this.x + ', ' + this.y + ')';  }}// 可以这么改写function Point(x, y) {  this.x = x;  this.y = y;}Point.prototype.toString = function () {  return '(' + this.x + ', ' + this.y + ')';};

登录后复制

class 里面定义的方法,其实都是定义在构造函数的原型上面实现实例共享,属性定义在构造函数中,所以 ES6 中的类完全可以看作构造函数的另一种写法

除去 class 类中的一些行为可能与 ES5 存在一些不同,本质上都是通过原型、原型链去定义方法、实现共享。所以,还是文章开始那句话  JavaScript是基于原型的

更多 class 问题,参考这里

关系判断

instanceof

最常用的确定原型指向关系的关键字,检测的是原型,但是只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型

function Person(){}var p = new Person();p instanceof Person // truep instanceof Object // true

登录后复制

hasOwnProperty

通过使用 hasOwnProperty 可以确定访问的属性是来自于实例还是原型对象

function Person() {}Person.prototype = {    name: 'tt'}var p = new Person();p.age = 15;p.hasOwnProperty('age') // truep.hasOwnProperty('name') // false

登录后复制

原型链的问题

由于原型链的存在,我们可以让很多实例去共享原型上面的方法和属性,方便了我们的很多操作。但是原型链并非是十分完美的

function Person(){}Person.prototype.arr = [1, 2, 3, 4];var person1 = new Person();var person2 = new Person();person1.arr.push(5) person2.arr // [1, 2, 3, 4, 5]

登录后复制

引用类型,变量保存的就是一个内存中的一个指针。所以,当原型上面的属性是一个引用类型的值时,我们通过其中某一个实例对原型属性的更改,结果会反映在所有实例上面,这也是原型 共享 属性造成的最大问题

另一个问题就是我们在创建子类型(比如上面的 p)时,没有办法向超类型( Person )的构造函数中传递参数

以上就是JS面试高频题 原型与原型链的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2731089.html

(0)
上一篇 2025年3月8日 00:25:05
下一篇 2025年3月8日 00:25:14

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • 快速了解UI组件功能设计

    组件能够大幅减轻开发的工作量,提升项目的可维护性,减少重复代码。本文主要讲解组件需要具备哪些功能,可以了解一下,希望你帮到你。 主体功能 主要功能是指这个组件是用来做什么的,如选择日期组件的目标是选择日期,下拉选择组件的目标是展示选项供用户…

    编程技术 2025年3月8日
    200
  • vue框架是什么

    Vue是一个MVVM的渐进式JavaScript框架,是初创项目的首选前端框架;它是轻量级的,有很多独立的功能或库,在vue里我们可以根据自己的项目来选用它的一些功能。 vue框架是什么?Vue框架是一个MVVM的渐进式JavaScript…

    2025年3月8日
    200
  • js是什么编程语言?

    js全称JavaScript,是一种具有函数优先的轻量级,直译式、解释型或即时编译型的高级编程语言,是一种属于网络的高级脚本语言;JavaScript基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式,如函数式编程。 本教…

    2025年3月8日
    200
  • javascript能做什么?

    JavaScript的用法有:1、创建炫酷的幻灯片;2,开发游戏;3,开发移动应用;4,Quadcopters控制;5,创建3D形状的特殊空间;6、运行Kinect等等。 【推荐课程:JavaScript教程】 JavaScript的基础知…

    2025年3月8日
    200
  • JavaScript中的垃圾回收和内存泄漏

    前言 程序的运行需要内存。只要程序提出要求,操作系统或者运行时就必须供给内存。所谓的内存泄漏简单来说是不再用到的内存,没有及时释放。为了更好避免内存泄漏,我们先介绍Javascript垃圾回收机制。 在C与C++等语言中,开发人员可以直接控…

    2025年3月8日 编程技术
    200
  • javascript 作用域详解

    作用域理解:定义的变量、函数生效的范围。javascript 有全局作用域和函数作用域两种。 注:es6实现let 块级作用域不是js原生的,底层同样是通过var实现的。如果想了解具体细节,请访问babel官方 对es6中let 进行解析。…

    编程技术 2025年3月8日
    200
  • 学javascript要什么基础?

    学习JavaScript需要有HTML和CSS的基础。学习javasctipt之前需要先学习一下HTML+CSS,因为javascript的基本操作就是控制html的标签以及css的属性,实现各式各样的动态功能。 JavaScript一种直…

    2025年3月8日
    200
  • JavaScript加载:defer与async

    页面的解析过程是单线程的,但是单线程亦可有同步与异步之分,script标签的解释方式分为3种,默认、defer和async三种 登录后复制登录后复制登录后复制登录后复制 默认模式,浏览器会立即加载并执行指定的脚本,“立即”指的是在渲染该 s…

    2025年3月8日
    200
  • jquery框架是什么?

    相信应该有一部分朋友听说过jquery吧,但是你了解它吗?你知道他是用来干嘛的吗?下面我将和大家一起谈谈什么是jquery框架。 jQuery就是一个快速、简洁的JavaScript框架。 jQuery,顾名思义是JavaScript和查询…

    2025年3月8日
    200
  • js中null是什么意思?

    在javascript中存在这样两种原始类型:null与undefined。这两种类型常常会使javascript的开发人员产生疑惑,null和undefined分别是什么意思呢? Null类型只有一个值,即null。null用来表示尚未存…

    2025年3月8日
    200

发表回复

登录后才能评论