资讯专栏INFORMATION COLUMN

一道简单的js继承面试题来查考你是否真的透彻的了解继承

jcc / 1843人阅读

摘要:但这两个对象的原型指向了同一个实例对象,这个实例对象同样是存在栈内存中的然后指向了一个对象。实际是在的实例对象增加一个属性,并将属性赋值为,但它并没有修改原型链上的属性。侧重理解的指向问题

直接先贴题目吧

 function A() {
    this.name = "a"
    this.color = ["green", "yellow"]
 }
 function B() {
   
 }
 B.prototype = new A()
 var b1 = new B()
 var b2 = new B()
 
 b1.name = "change"
 b1.color.push("black")

console.log("b1", b1)

console.log("b2", b2)

console.log(b1.name) // change
console.log(b2.name) // a
console.log(b1.color) // ["green", "yellow", "black"]
console.log(b2.color) // ["green", "yellow", "black"]

这其实就是我们的常见继承模式之一,原型继承,为何会出现这样的情况呢?
最大的疑惑是,为何两个实例对象b1,b2里面的color属性都被修改了?
又为何b1.name = change 而b2.name 却没有发生改变。
首先,你得有原型链继承的知识点,有了这个知识点后,我们再理解下我们经常挂在嘴边的基本数据类型和
引用数据类型,他们的存储方式和读取方式有何异同,带着这一些疑惑,我们再看下栈内存的概念

看了上图,一目了然的看到,不管是基本数据类型还是引用类型,实际都是存在栈内存的,只不过引用数据类型还会指向一个具体的堆。他们的区别我简单就阐述这么一些。

再剖析上面的代码是如何执行或者指向的。
首先:b1和b2实例化是存在栈内存里面,然后指向了堆内存的两个对象。但这两个对象的原型指向了同一个实例对象,这个实例对象同样是存在栈内存中的(然后指向了一个对象)。所以简而言之,b1和b2的原型对象指向了同一个实例对象(A的实例对象)。

b1.name = "change"

实际是在b1的实例对象增加一个属性name,并将name属性赋值为change,但它并没有修改原型链上的name属性。

b1.color.push("black")

这里涉及到原型链向上查找属性的知识点,实例对象b1里面并没有color属性,于是去原型链上寻找,结果在A的实例对象找到了color,但此时的color属性指向的是一个引用类型,而b1和b2都继承于A这个实例对象,根据引用类型color指向一个堆数组来看,当b1修改了原型上的color属性,实际也就修改了b2上面的color属性。再强调下,因为color属性是原型对象上的一个引用类型属性,指向了同一个数组对象

那么如何规避color属性被指向同一个引用类型的问题呢?
实际我们上面就是运用到继承里面的一个原型链继承的方法。
还有一种继承是构造函数继承
稍微修改下:

function B() {
  A.call(this)  
}

经过改动后,我们每次在实例化B的时候,会将实例化对象的引用对象作为参数传递到B这个构造函数,在间接调用A函数的时候,也修改了A执行的时候this的执行问题。此时this的执行不再是window而是实例化的对象b1或b2.
分析下,我们不写A.call(this)这句代码的时候,A的实例对象实际就是指向A实例对象的本身,这句话理解起来有点傲,执行了A.call(this)后,这里翻译过来我想应该是这样的,不知道是否有错?

调用A,而不是实例化A,即A(),但此时A的this并不是window对象,这里没有实例A所以,this不是A实例化指向的那个引用对象。然后我们认为的修改了A这个函数执行时执行上下文的this执行,这个this此时成了b1或者b2实例对象。

此时我们再修改b1.color的时候,同样会去原型上去找color熟悉,但此时原型链上的this已经指向了b1这个实例化对象,所以当我们修改b1.color的时候,实际只修改了b1这个实例化对象对应原型上的那个对象。而b2.color并不会被改变。侧重理解this的指向问题

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93865.html

相关文章

  • 基本方法笔记 - 收藏集 - 掘金

    摘要:探讨判断横竖屏的最佳实现前端掘金在移动端,判断横竖屏的场景并不少见,比如根据横竖屏以不同的样式来适配,抑或是提醒用户切换为竖屏以保持良好的用户体验。 探讨判断横竖屏的最佳实现 - 前端 - 掘金在移动端,判断横竖屏的场景并不少见,比如根据横竖屏以不同的样式来适配,抑或是提醒用户切换为竖屏以保持良好的用户体验。 判断横竖屏的实现方法多种多样,本文就此来探讨下目前有哪些实现方法以及其中的优...

    maochunguang 评论0 收藏0
  • JS核心知识点梳理——上下文、作用域、闭包、this(中)

    摘要:引言满满的干货,面试必系列,参考大量资料,并集合自己的理解以及相关的面试题,对核心知识点中的作用域闭包上下文进行了梳理。本篇重点介绍闭包和。所以,有另一种说法认为闭包是由函数和与其相关的引用环境组合而成的实体。 showImg(https://segmentfault.com/img/bVbo4hv?w=1800&h=1000); 引言 满满的干货,面试必bei系列,参考大量资料,并集...

    rottengeek 评论0 收藏0
  • JavaScript系列(四) - 收藏集 - 掘金

    摘要:函数式编程前端掘金引言面向对象编程一直以来都是中的主导范式。函数式编程是一种强调减少对程序外部状态产生改变的方式。 JavaScript 函数式编程 - 前端 - 掘金引言 面向对象编程一直以来都是JavaScript中的主导范式。JavaScript作为一门多范式编程语言,然而,近几年,函数式编程越来越多得受到开发者的青睐。函数式编程是一种强调减少对程序外部状态产生改变的方式。因此,...

    cfanr 评论0 收藏0
  • 一道面试题引发思考

    摘要:下面我们来使用面向对象类图这里就不再画了首先面试题中所提到的我们都可以看成类,比如停车场是一个类吧,它里面的车位是一个类吧,摄像头,屏幕。。。 以下是某场的一道面试题(大概): 1、一个停车场,车辆入场时,摄像头记录下车辆信息2、屏幕上显示所接收的车辆的信息情况(车牌号)以及各层车位的车位余量3、停车场一共四层车位,其中的三层都为普通车位,还有一层为特殊车位(体现在停车计费价格上面的不...

    Apollo 评论0 收藏0

发表评论

0条评论

jcc

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<