2018年3月面试心得《原型、原型链》

以前的文章地址:
2018年3月面试心得《跨域问题》
2018年3月面试心得《上下文,做用域》前端

想了半天,我仍是对原型下手了。
近期面试的小伙伴们确定也是面临着很多原型的问题。es6

“请你简单描述一下原型。”
——原型就是爸爸,原型链就是爸爸的基因。
“如何实现继承?” ——es6的extends。 “es5呢?”
——………(脸上笑嘻嘻,内心fuuuuuuuuuuuck!!!)

我想应该有很多转专业到前端来的小伙伴跟我同样,基础弱的一笔,抓了几个面试题刷了刷,完事英勇的冲了出去,昂首挺胸的被问几句,答上来了自信心爆表,可是面试官再问细一点,立马就蔫巴了~
不得不说,大厂都会抓着你基础死劲问,由于他们认为基础决定一切。(他们是否是这么认为的我也不知道,可是给我感受就是这样……)
接下来,咱们要好好的来巩固一下原型的基础啦。面试

首先,咱们先玩个函数。

// 我先个你一个儿子的设计图
function 儿子(name, age, isGay) {
    this.name = name;
    this.age = age;
    this.isGay = true;
}

// 如今我要开始造儿子了!!!
var myson = new 儿子('小明', 50, false)

// 如今打印一下咱们的myson
//{name: "小明", age: 50, isGay: true}

// 卧槽怎么回事,我儿子怎么是个gay!不行!
myson.isGay = false

// 好了这下舒坦了 嘿嘿嘿嘿

上面的这个就是构造函数,咱们也能够叫他为儿子生成器,或者图纸。
咱们拿着图纸去生成不一样的儿子,儿子你又能够给他新的属性等等~你能够diy~
是否是颇有意思。
好了咱们进入正题。segmentfault


普通对象和函数对象

JavaScript中万物皆对象,但对象之间也是有区别的。分为普通对象函数对象跨域

咱们大前端是不怕单身的,没对象能够new一个。
在看代码的时候,常常会看到这些东西。函数

var a = new Object;
var b = new funxtion() {……}

这就是被咱们new出来的对象。
很明显,上面的是普通对象,下面的是函数对象。性能

普通对象若是加上了prototype的属性,那么就变成了原型对象。
每一个函数对象建立的时候,都会自带一个prototype的属性,这个属性至关于一个指针,指向他自己的原型对象,这个原型对象里包含着自定义的方法属性学习

好了,让咱们来实践一下,首先咱们要作一只猫咪和一只狗狗。this

var miao;
miao.prototype = {
    name = "大蛋蛋",
    age = 1
}
function dog(name, age){
    this.name = name,
    this.age = age
}

// 如今咱们把猫狗的图纸画好了,上面是原型对象的方式,下面是函数对象,接下来咱们就能够来建立一些猫猫狗狗了。

咱们停一下

昨晚在我写到这里的时候,去看了一本书,上面写着其实js的继承,其实并不该该叫继承。
在其余语言中,继承是属于复制。es5

创造了一个爸爸,那么继承就是我复制了不少爸爸出来,每一个爸爸都同样的。
固然你也能够给你创造的每一个爸爸一些单独的属性,这个爸爸会作饭,那个爸爸会钓鱼。

在you don`t know js里面的第五章写着:

原本设计js语言的时候并无想将它作的太过复杂。
经过new的函数调用并无创造关联,这个关联只是一个**意外的反作用**。

这个观点我目前还不是太清楚对错,可是咱们能够暂时先这么理解一下。

若是说其余语言的继承,就是复制的话,你创造一个爸爸图纸,能够做出不一样的爸爸。

那么js的理解应该就是,你创造一个爸爸,而且生出一堆儿子,每一个儿子都 能够拥有爸爸给孩子的东西,例如钓鱼、作饭(爸爸的方法)。

为何会拥有他的方法呢?

由于在儿子尚未学习这个方法的时候,咱们班主任让儿子去钓鱼,那么儿子不会,就会向上查找去叫爸爸,若是爸爸有这个技能,咱们就能够成功完成任务了。

如今咱们来用作简单的语言来阐述一下原型和原型链。
什么是原型?那就是爸爸。
什么是原型链?那就是爸爸和儿子的关系。

不知道这么解释会不会有点牵强,不过这确实能够有助于咱们去实践下一步。


如今开始真正的实践。

咱们仍是简单去作一个爸爸吧。

function 爸爸(name) {
    // 如今我给爸爸丢上一些方法
    // 给孩子命名
    this.name = name;
    // 爸爸愿意交给儿子能够钓上来你想要的鱼
    this.goFishing = function(fis) {
        return fis
    }
}
// 如今咱们来创造儿子
var 儿子小明 = new 爸爸('小明')

儿子小明.name //"小明"
儿子小明.goFishing('章鱼') //"章鱼"

// 爸爸没有直接较
爸爸.prototype.cook = function () {
    ['米饭', '爆炒鱿鱼', '番茄蛋汤'].forEach(i => console.log(i))
}
儿子小明.cook()
// 米饭 爆炒鱿鱼 番茄蛋汤

如今咱们打印一下小明儿子。
儿子里面有:{name: "小明", goFishing: ƒ}
这是爸爸直接给儿子的东西。
那么爸爸还没给儿子,儿子却可使用的到哪里去了呢?

咱们往下再看,有一个__proto__
在这里面,就能发现爸爸的cook。

因此爸爸的独门绝技丢在了prototype里面,这里面是儿子不须要学习却能够直接使用的独门绝技~

构造函数属性(constructor)

这个又是什么呢?
其实在刚刚咱们打印儿子小明的时候,在cook下面,有一个constructor的东西,就是这玩意。
仍是刚刚的代码,如今跟着我一块儿打印一下儿子小明.constructor
如今直接把爸爸打印出来了。

这个怎么理解呢……
我找到了一句话。

在默认状况下,全部的原型对象都会自动得到一个 constructor(构造函数)属性,这个属性(是一个指针)指向 prototype 属性所在的函数(Person)

好了,就按照这句话这么理解的话,咱们能够理解为:

全部的儿子都会有一个constructor的属性,这个属性指着能够获取爸爸独门绝技(prototype)的那个爸爸。

如今我叫他找爸爸属性……

如今咱们再建立一个女儿

var 女儿小花 = new 爸爸('小花')

儿子小明.constructor === 女儿小花.constructor // ture

那咱们用了找爸爸属性,因此小明和小花的爸爸是同一个爸爸~

如今咱们再仔细看一下刚刚打印出来的小明。

敲黑板。

goFishing:ƒ (fis)
name:"小明"
__proto__:{
    cook:ƒ ()
    constructor:ƒ 爸爸(name)
    __proto__:Object
}

仔细看,constructor在哪里~
大声告诉我在哪里~
在__proto__里面对吧。
因此这个找爸爸的属性是从爸爸那里带过来的,是爸爸告诉你怎么找爸爸,而且没有实际教会你怎么找爸爸,是直接调用爸爸的独门绝技找的爸爸~

狂敲黑板!

如今咱们再来往下科普一下其余的几个数据类型,再研究其原型。

它是 JavaScript 语言的第七种数据类型,前六种是:undefined、null、布尔值(Boolean)、字符串(String)、数值(Number)、对象(Object)
还有ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。

咱们如今先来玩一下数字。

var 数字 = 12;
// 他是否有爸爸呢?
console.log(数字.__proto__)
// 跟着我敲敲看。
var 数字1 = new Number(12)
数字 == 数字1 // true
数字 === 数字1 // false

在打印数字的proto的时候,瞧咱们看到了什么!
Number!
这就是他爸爸!

最后谈一下继承的方法吧。

es6:

Class 能够经过 extends关键字实现继承,这比 ES5 的经过修改原型链实现继承,要清晰和方便不少。
子类必须在constructor方法中调用 super方法,不然新建实例时会 报错。这是由于子类 没有本身的this对象,而是 继承父类的this对象,而后对其进行加工。若是不调用super方法,子类就 得不到this对象。

es5:

方法一:

子.prototype = new 爸爸()

新建一个爸爸做为孩子的独门绝技~
可是要想为儿子新增属性和方法,必需要在new 爸爸()这样的语句以后执行,不能放到构造器中……
来自原型对象的引用属性是全部实例共享的,建立子类实例时,没法向父类构造函数传参

方法二:

function 儿子(name){
 父亲.call(this);
 this.name = name || 'Tom';
}

可是这样的话,每一个儿子都要绑定爸爸的实例函数的副本,影响性能

方法三:

儿子.prototype = Object.create(爸爸.prototype)
创造一个新爸爸的独门绝技来当儿子的独门绝技~

其实方法有不少,我就不一一举例了。

ECMAScript 继承机制实现

若是对文章有什么间接,欢迎悄悄告诉我~ =333333=
么么哒~上面我还写了数字和数字1,猜猜看我下一章写的是啥~~~

相关文章
相关标签/搜索