javascript学习笔记(17)--prototype

引入

javascript的原型继承其实是比较麻烦的,涉及的东西挺多的…网上的都挺散的
上一节简单的讲了一下原型和创建对象,最后讲了下原型链,原型链里面有个关键字prototype
这个之前可能一直都没有关注过,但他其实一直潜伏在javascript里面
比如说我们这个简单的数组,不知道你有没有打开那个看看,下面会有一项prototype
在这里插入图片描述

什么是prototype

prototype
原型;雏形;最初形态
在这里我们取原型的意思
原型这个概念可能很好理解,可以理解为就是模板,其他的都是靠这个模板复刻的,刚好这个也很像类的概念,这个原型就类似于一个class, 由他可以创造出一个个实例
这就是我们Array的原型,也就是上面那张图里下面的prototype
在这里插入图片描述可以看到,这里面有很多很多的函数,结合上节的内容,通过原型继承可以获得原型的函数,所以我们才会有a.shift()等等操作,其实都是通过访问原型实现的

细心的同学可以发现,在最下面,还有一个原型,那这个原型又是什么呢
在这里插入图片描述在这里插入图片描述展开Array.prototype可以发现他的内容其实和Object.prototype是一致的,而且Object.prototype下面没有prototype了

prototype的作用

首先prototype可以体现并追溯原型链
我们通过展开对象,可以看到他的prototype,也就是对应着他的原型
注意,只有object和function可以查看prototype,其他的无法查看
在这里插入图片描述Object.prototype是最上层的原型,所有的原型都会指向这个原型,Object.prototype也是构成这个js世界的基石
同时通过prototype也可以查看我们到底继承了哪些东西,可以使用哪些方法

上面这些只是刚刚热身,下面才是真正的烧脑

更深层次

我们之前创造一个数组都是使用的

var a=[1,2,3]

但实际上,他是这个函数的缩写

var b=Array([1,2,3])

我们是通过调用Array这个函数来创建这个数组的
口说无凭,凭什么他们一样
有些同学可能会想到,那我可以用==来判断他们是否一样呀

误区,==和===的使用
number,string,bool,undefiend这4种类型可以直接用==比较是否相等,判断原理是根据他们的值来判断,值一样就是相等(函数没有比较意义,就排除了)
然而对于object和function, ==和===比较的时候实际在比较他们地址,(因为object和function本身过于复杂)
我们以为通过==可以比较两个object属性和值,但实际上是他们的地址,所以无法用这个==的方法判断object是否一直需要我们自己设计函数实现
在这里插入图片描述
但实际上两个是一样的
在这里插入图片描述

不过上面不是今天的重点,重点是要引入Array这个函数
在这里插入图片描述
这个就是我们的Array,这里出现了两个porototype,一个是灰色,一个是蓝色
灰色的刚才我们已经见过,他是指向上级原型的,它实际上显示的是上级原型的prototype,这里也就是Object.prototype(Array.prototype的上级)
而蓝色对应的是这个函数本身具有的prototype

首先解释第一个问题
什么样的对象有prototype
这里专指蓝色的
在这里插入图片描述在这里插入图片描述其实这么多javascript对象里,只有function有自己的原型
为什么
这不得不要提到为什么需要prototype
这就涉及到函数

私有
之前我们讲过函数作用域,在函数内定义的变量和函数如果不对外提供接口,那么外部将无法访问到
在这里插入图片描述
我们在函数内部定义了b变量和s函数,只能在函数内部使用,外部和函数的实例仍然无法访问这些变量和函数
上面这种变量称为私有变量

静态
当定义一个函数后通过 “.”为其添加的属性和函数,通过对象本身仍然可以访问得到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量和静态函数
在这里插入图片描述
注意,静态变量前不能用var不然会报错
在这里插入图片描述
其次,函数执行后静态变量才有效果

在这里插入图片描述
其实个人感觉吧,静态变量和私有变量效果差不多,只不过第二种定义有点属性的感觉
外部无法访问静态变量,实例化的对象也无法访问函数的变量

实例
在面向对象编程中除了一些库函数我们还是希望在对象定义的时候同时定义一些属性和方法,实例化后可以访问
在这里插入图片描述
在这里插入图片描述
可以看到,这样定义其实比较尴尬,因为我们的函数是在window下面,所以调用的时候其实他指向的是我们的window,而我们window又没有继承我们的函数,所以其实我们这样实例化的结果是我们不能再访问我们的变量了(区分开之前的静态变量,静态变量绑定了this,这个没有绑定this)
而我们实例化之后,相当于继承了函数的属性,而且this分别绑定到了自己上面,互不干扰,我的属性修改跟你的没关系,最开始继承的结果是我们函数内部定义的初始化值(这也可以解释为什么私有变量和静态变量无法访问,因为this绑定的问题,不可以越界)
但这样有个缺点,就是缺少协同性,相当于我们彼此互不干扰,都是复制的结果,如果我们的方法出了错,想要去修改,还必要修改每一个实例

prototype
为了解决以上种种麻烦,prototype运营而生
在这里插入图片描述可以看到,实例化的对象可以直接访问到prototype的值,而函数还是要先执行一下才可以访问到,然后通过push追加的方式也可以实现共享,修改了prototype的值也会传递
在这里插入图片描述
但是要注意,如果直接修改实例化对象的值则不行

在这里插入图片描述
在这里插入图片描述这个其实好理解,还是跟共享的原理有关系
之前可以同步是因为我们实例化对象里其实上面属性和值都没有,当我们执行t2.a,t1.a的时候实际上是在访问prototype.a,所以可以做到同步
而我们一旦执行了t1.a=1;相当于就给t1增加了个属性a:1,这个时候由于优先级的问题,她就不会去访问你的prototype了,直接给你覆盖掉了

比较了四种变量后直到prototype有什么好处了吗,这下次也可以理解为什么函数都会有prototype了吗,如果不理解的话多看几遍啦

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章