请务必搞懂原型(附你想不到的网易面试题)

浅聊一下

JavaScript 中的原型是理解该语言核心特性的关键之一。在面试中,掌握原型概念通常是一个重要的议题。今天我们将深入探讨 JavaScript 中的原型,并且文章末尾附带一道你绝对想不到的网易面试题…

什么是原型?

我们先来聊聊到底什么是原型

原型(prototype)是函数天生就具有的属性,它定义了构造
函数制造出的对象的公共祖先。
通过该构造函数产生的对象,可以隐式继承到原型上的属性和方法

你说这到底是啥呀?语文不好,看不懂…那我们直接上代码

function Person() {
    this.name = '张三';
    this.age = 18;
}
let p = new Person();
console.log(p);

在js中,我们用这种方法定义一个类,然后new一下创造一个对象,代码较为简单,来看打印结果

请务必搞懂原型(附你想不到的网易面试题)
我们可以看到,所创建的对象p继承到了Person( )中的属性,并且可以打印出来看到,那么我们再来上一段代码

Person.prototype.say = function () {
    return '我是张三'
}
console.log(p.say());
console.log(p);

这次我们调用p.say()

请务必搞懂原型(附你想不到的网易面试题)
在这里我们可以看到p.say()确实被调用了,说明p身上确实有这个方法,但是打印p的时候却没有显示出来,于是乎,我们可以称function Person()是p的显示原型,而Person.prototype是p的隐式原型

为什么需要原型?

因为可以提取公有属性,简化代码执行

你说这话说的这么简陋,我还是看不懂…话又不多说,直接上代码

Car.prototype.name = 'BMW';
Car.prototype.lang = 4900; 
Car.prototype.height = 1400;
function Car(owner,color){
    this.owner = owner;
    this.color = color;
}
var car = new Car('L','black');
var car2 = new Car('Y','pink');

这里有一个“别摸我”牌汽车的构造函数,Car构造函数的原型上我们定义了公共属性,而函数里有有颜色和拥有者,这些是需要“私人定制”的,所以在new一个对象的时候,相同的属性就不会再重复创建,直接访问隐式原型就可以访问到。在这里“L”和“Y”分别购买了一辆“别摸我”,并且分别定制了颜色…

细节

  • 实例对象是无法修改原型的属性和方法的
Car.prototype.name = 'BMW';
Car.prototype.lang = 4900;
Car.prototype.height = 1400;
function Car(owner,color){
    this.owner = owner;
    this.color = color;
}

var car = new Car('L','black');
var car2 = new Car('Y','pink');
car.name = '劳斯莱斯'
console.log(car);
console.log(car2.name);

聪明的掘友来看看这里输出什么?

请务必搞懂原型(附你想不到的网易面试题)

我们本意上是想修改他们公共属性上的name,我让car.name=“劳斯莱斯”,但是将他们打印出来以后,我们发现car2的名字任然没有改变,就像“别摸我”公司卖给我一辆汽车,我叫其中的一辆为大黄,但是你并不能改变他的品牌名字叫“别摸我”吧…

那么我们怎么修改他们公共的名字呢?让公司改名呗!

Car.prototype.name = '大黄';
console.log(car);
console.log(car2.name);

太狠了,把公司名都改了…现在叫大黄

请务必搞懂原型(附你想不到的网易面试题)

  • 实例对象是无法删除原型的属性和方法的

既然个人是无法改变品牌的名字的,那么我个人要把你品牌的名字删了,那你能忍?

Car.prototype.name = 'BMW';
Car.prototype.lang = 4900;
Car.prototype.height = 1400;
function Car(owner,color){
    this.owner = owner;
    this.color = color;
}

var car = new Car('L','black');
var car2 = new Car('Y','pink');

car.name = '劳斯莱斯'
Car.prototype.name = '大黄';
delete car.name
console.log(car);
console.log(car2.name);

不用猜,你只能剥夺你自己车的名字,而car和car2的品牌名依旧叫大黄

请务必搞懂原型(附你想不到的网易面试题)

要删除品牌名,同样得让公司自己改呀!

Car.prototype.name = 'BMW';
Car.prototype.lang = 4900;
Car.prototype.height = 1400;
function Car(owner,color){
    this.owner = owner;
    this.color = color;
}

var car = new Car('L','black');
var car2 = new Car('Y','pink');

car.name = '劳斯莱斯'
Car.prototype.name = '大黄';
// delete car.name
delete Car.prototype.name
console.log(car.name);
console.log(car2.name);

由于你自己叫自己的车为劳斯莱斯,所以car的名字还是有的
请务必搞懂原型(附你想不到的网易面试题)

原型链

原型链是什么呢?

顺着对象的隐式原型不断向上查找上一级的隐式原型,直到找到目标或者一直到null,
这种查找关系称为原型链

举一个例子,你把别人的“别摸我”撞坏了,他找你(你的显示原型)赔钱,你拿不出,找你老婆(你的隐式原型),他就找到你爸爸(你爸爸的显示原型),你爸爸拿不出就找到你妈妈(你爸爸的隐式原型),你妈妈也拿不出,于是找你爷爷(爷爷的显示原型),又找不到,还找你奶奶(爷爷的隐式原型),再往上没人了,于是只能认栽…

原型链也是这样,小二,上个代码

<script>

    Ground.prototype.lastName = "wang";
    function Ground(){

    }
    var ground = new Ground();
    Father.prototype = ground;
    function Father(){
        this.name = "zhangsan";
    }
    var father = new Father();
    Son.prototype = father;
    function Son(){
        this.hobbit = "play";
    }
    var son = new Son();
    console.log(son.lastName+son.name);

</script>

让我们逐步分析:

  1. 首先,定义了一个名为 Ground 的构造函数,然后给 Ground.prototype 对象添加了一个 lastName 属性,其值为 “wang”。
  2. 接着,定义了一个 Father 构造函数,其中通过 this.namename 属性设置为 “zhangsan”。
  3. 然后,创建了一个 ground 对象实例,它的原型是 Ground.prototype。由于 Ground.prototype 上有 lastName 属性,所以 ground 实例也能访问到 lastName 属性。
  4. 接下来,将 Father.prototype 设置为 ground 对象,这样 Father 构造函数的实例将会继承 ground 对象的属性和方法。
  5. 定义了一个 Son 构造函数,其中通过 this.hobbithobbit 属性设置为 “play”。
  6. 最后,创建了一个 son 对象实例,它的原型是 Father.prototype,因此它继承了 Father 构造函数中的 name 属性,同时也能通过原型链访问 lastName 属性。因此,console.log(son.lastName + son.name) 会输出 “wangzhangsan”。

你想不到的网易面试题

所有的对象最终都会继承自 Object.prototype?

乍一看,好像没什么不对劲,可这个“所有”两个字又让人望而生畏,那么答案到底是什么呢?
错!大错特错

为什么?,因为我们还有一种创建对象的方法Object.create()

<script>
    //Object.create(obj)
    let obj = {
        a:1
    }
    let obj2 = Object.create(obj)
</script>

来看看打印obj2的结果

请务必搞懂原型(附你想不到的网易面试题)

在这里我们可以看到obj2继承了obj,那么我们再来看

let obj3 = Object.create(null)

再来打印obj3

请务必搞懂原型(附你想不到的网易面试题)
我们可以看到并没有报错,obj3里面什么也没有,并没有继承到Object

这是为什么呢?这里涉及到一个美丽的错误,我们的null用typeof判断出来的类型可是Object啊
至于为什么,大家可以去我以前的文章看看(“探秘JavaScript:类型判断的奇妙世界(一)” – 掘金 (juejin.cn))

请务必搞懂原型(附你想不到的网易面试题)

结尾

原型看完这篇基本上就搞定了,舒舒服服上床睡觉等待过年,嘿嘿嘿……

原文链接:https://juejin.cn/post/7332708703399673897 作者:滚去睡觉

(0)
上一篇 2024年2月9日 上午10:16
下一篇 2024年2月9日 上午10:26

相关推荐

发表回复

登录后才能评论