浅聊一下
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>
让咱们逐渐剖析:
- 首先,界说了一个名为
Ground
的结构函数,然后给Ground.prototype
目标添加了一个lastName
特点,其值为 “wang”。 - 接着,界说了一个
Father
结构函数,其间经过this.name
将name
特点设置为 “zhangsan”。 - 然后,创立了一个
ground
目标实例,它的原型是Ground.prototype
。因为Ground.prototype
上有lastName
特点,所以ground
实例也能拜访到lastName
特点。 - 接下来,将
Father.prototype
设置为ground
目标,这样Father
结构函数的实例将会承继ground
目标的特点和办法。 - 界说了一个
Son
结构函数,其间经过this.hobbit
将hobbit
特点设置为 “play”。 - 最后,创立了一个
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))
结束
原型看完这篇基本上就搞定了,舒舒服服上床睡觉等待春节,嘿嘿嘿……