JavaScript原型详解
1,前言
下面是2008年Github创建以来,各种编程语言的排名情况
排名
其中JavaScript自2015年之后就盘踞第一名,成为github上被使用最多的语言,早期,JS的使用还主要集中于浏览器中,但是随着node.js进军服务器开发和React Native逐渐向移动端渗透,一个属于JS的全栈时代就要来临了。而且JS界还流传一句名言:“所有能用JS开发的应用程序,最终都会用JS来开发”。我就问你怕不怕?
好了,说了这么多,我并不是想说JS为世界上最好的语言(显然PHP才是,对吧?←_←),也不是觉得JS会替代谁,我只是觉得,JavaScript将会是一个大家(不止web端)都应该了解和学习的语言工具。
2,面对对象(OOP)
2.1 实现思路
面对对象是大家都很熟悉的程序设计思想,是对真实世界的抽象,目前主要OOP语言用来实现面对对象的基础是类,通过类的封装,继承来映射真实世界。包括Java,C#,甚至是python等都通过类的设计来实现面对对象。但是细想起来也会觉得有问题,因为真实世界其实没有类这种概念,只有一个个不同的对象,真实世界中,继承关系发生在对象和对象之间,而不是类。就比如孩子是对象,父母也是对象,孩子(对象)继承自父母(对象)
JS也是面对对象的编程语言,只不过它实现面对对象的思路是基于原型(prototype),而不是类。这种思路也叫对象关联(Object Link Other Object),即在对象上直接映射那种真实世界的关系(如继承)。
2.2 原型概念
相关的概念其实我研究了好几天,除开原型概念本身,与之联系的对象的产生,构造函数,proto,prototype的区别,为什么对象没有prototype这个指向原型的属性,而是使用proto来指向原型?
好,我们先来谈谈原型这个概念。JS中一切皆对象,而每个对象都有一个原型(Object除外),这个原型,大概就像Java中的父类,所以,基本上你可以认为原型就是这个对象的父对象,即每一个对象(Object除外)内部都保存了它自己的父对象,这个父对象就是原型。一般创建的对象如果没有特别指定原型,那么它的原型就是Object(这就很类似Java中所有的类默认继承自Object类)。
2.3 对象创建
在JS中,对象创建的方法有很多种,最常见的如下:
//第一种,手动创建
var a={'name':'lala'}; //第二种,构造函数
function A(){
this.name='lala';
}
var a=new A(); //第三种,class (ES6标准写法) class A{
constructor(){
//super();此处没有使用extends显式继承,不可使用super()
this.name='lala';
}
}
var a=new A()
//其实后面两种方法本质上是一种写法
这三种写法创建的对象的原型(父对象)都是Object,需要提到的是,ES6通过引入class ,extends等关键字,以一种语法糖的形式把构造函数包装成类的概念,更便于大家理解。是希望开发者不再花精力去关注原型以及原型链,也充分说明原型的设计意图和类是一样的。
2.3 查看对象原型
当对象被创建之后,查看它们的原型的方法不止一种,以前一般使用对象的proto属性,ES6推出后,推荐用Object.getPrototypeOf()方法来获取对象的原型
function A(){
this.name='lala';
}
var a=new A();
console.log(a.__proto__)
//输出:Object {} //推荐使用这种方式获取对象的原型
console.log(Object.getPrototypeOf(a))
//输出:Object {}
无论对象是如何创建的,默认原型都是Object,在这里需要提及的比较特殊的一点就是,通过构造函数来创建对象,函数A本身也是一个对象,而A有两个指向表示原型的属性,分别是proto和prototype,而且两个属性并不相同
function A(){
this.name='lala';
}
var a=new A();
console.log(A.prototype)
//输出:Object {} console.log(A.__proto__)
//输出:function () {}
console.log(Object.getPrototypeOf(A))
//输出:function () {}
函数的的prototype属性只有在当作构造函数创建的时候,把自身的prototype属性值赋给对象的原型。而实际上,作为函数本身,它的原型应该是function对象,然后function对象的原型才是Object。
总之,建议使用ES6推荐的查看原型和设置原型的方法。
2.4 原型的用法
其实原型和类的继承的用法是一致的:当你想用某个对象的属性时,将当前对象的原型指向该对象,你就拥有了该对象的使用权了。
function A(){
this.name='world ';
}
function B(){
this.bb="hello"
}
var a=new A();
var b=new B(); Object.setPrototypeOf(a,b);
//将b设置为a的原型,此处有一个问题,即a的constructor也指向了B构造函数,可能需要纠正
a.constructor=A;
console.log(a.bb)
//输出 hello
(增补)
如果使用ES6来做的话则简单许多,甚至不涉及到prototype这个属性
class B{
constructor(){ this.bb='hello'
}
}
class A extends B{
constructor(){
super()
this.name='world'
}
} var a=new A();
console.log(a.bb+" "+a.name);
//输出hello world console.log(typeof(A))
//输出 "function"
怎么样?是不是已经完全看不到原型的影子了?活脱脱就是类继承,但是你也看得到实际上类A 的类型是function,所以说,本质上class在JS中是一种语法糖,JS继承的本质依然是原型,不过,ES6引入class,extends 来掩盖原型的概念也是一个很友好的举动,对于长期学习那些类继承为基础的面对对象编程语言的程序员而言。
我的建议是,尽可能理解原型,尽可能用class这种语法糖。
2.5 原型链
这个概念其实也变得比较简单,可以类比类的继承链条,即每个对象的原型往上追溯,一直到Object为止,这组成了一个链条,将其中的对象串联起来,当查找当前对象的属性时,如果没找到,就会沿着这个链条去查找,一直到Object,如果还没发现,就会报undefined。那么也就意味着你的原型链不能太长,否则会出现效率问题。
3,总结
- 对于原型概念的理解
- 类比类的继承,对象的原型可以理解为对象的父对象
- 原型的运用
- 尽可能使用ES6的标准,使用class,extends,Object.getPrototype(),Object.setPrototype()等等
- 需要注意的点
- 原型继承链条不要太长
- 指定原型时,注意constructor也会改变。
4,后记(增补)
还有人觉得我的分析很抽象,所以,我再总结一下,如果要一句话理解JS中的原型是什么,那就是,对象的原型就指的对象的父对象。每个对象都有父对象,父对象本身也有父对象(爷对象?)。而原型链呢,很像过去家谱的概念,可以从你往上追溯你父亲,到爷爷,到太爷爷一直到头,这就形成了一个链条,如果其中每个人都比作一个对象,那么这个链条就是原型链。
本文出处:掘金 http://gold.xitu.io/post/57f336a9816dfa00568f300c
JavaScript原型详解的更多相关文章
- javascript 原型详解
引:http://www.cnblogs.com/wangfupeng1988/p/3978131.html 1.什么是javascript原型 每一个函数都有prototype属性(默认生成的)和原 ...
- JavaScript事件详解-jQuery的事件实现(三)
正文 本文所涉及到的jQuery版本是3.1.1,可以在压缩包中找到event模块.该篇算是阅读笔记,jQuery代码太长.... Dean Edward的addEvent.js 相对于zepto的e ...
- javascript 函数详解2 -- arguments
今天我们接着上篇文章来继续javascript函数这个主题.今天要讲的是函数对像中一个很重要的属性--arguments. 相关阅读: javascript 函数详解1 -- 概述 javascrip ...
- [原创]JavaScript继承详解
原文链接:http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html 面向对象与基于对象 几乎每个开发人员都有面向对象语言(比如C++. ...
- JavaScript事件详解-Zepto的事件实现(二)【新增fastclick阅读笔记】
正文 作者打字速度实在不咋地,源码部分就用图片代替了,都是截图,本文讲解的Zepto版本是1.2.0,在该版本中的event模块与1.1.6基本一致.此文的fastclick理解上在看过博客园各个大神 ...
- JavaScript正则表达式详解(一)正则表达式入门
JavaScript正则表达式是很多JavaScript开发人员比较头疼的事情,也很多人不愿意学习,只是必要的时候上网查一下就可以啦~本文中详细的把JavaScript正则表达式的用法进行了列表,希望 ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
- JavaScript事件详解-zepto的事件实现
zepto的event 可以结合上一篇JavaScript事件详解-原生事件基础(一)综合考虑源码暂且不表,github里还有中文网站都能下到最新版的zepto.整个event模块不长,274行,我们 ...
- javaScript基础详解(1)
javaScript基础详解 首先讲javaScript的摆放位置:<script> 与 </script> 可以放在head和body之间,也可以body中或者head中 J ...
随机推荐
- unsupported time zone specified undefined
unsupported time zone specified undefined 出现了这个问题,莫名其妙的,上次被我下回去了,真的是下回去的,我一去查看,坐在电脑前面问题就不见了…… 具体出现 ...
- composer 下载包慢的解决方法
方法一: 修改 composer 的全局配置文件(推荐方式) 打开命令行窗口(windows用户)或控制台(Linux.Mac 用户)并执行如下命令: composer config -g repo. ...
- python之路--MySQL多表查询
一 介绍 我们在写项目的时候一般都会建一个数据库,数据库里面会存很多的表,不可能把所有的数据都放在一张表里,因为分表来存数据节省空间,数据的组织结构更清晰,解耦和程度更高,但是这些表本质上还不是一个整 ...
- linux audit审计(6)--audit永久生效的规则配置
定义reboot系统后,仍然生效的审计规则,有两种办法: 1.直接写入/etc/audit/audit.rules文件中,在service文件中需要加入ExecStartPost=-/sbin/aud ...
- wiki 安装
地址:https://www.jianshu.com/p/fb2574567eae
- SLAs-笔记
类型 sla status determined at time intervals over a timeline: average transaction response time errors ...
- SOJ 1685:chopsticks(dp)
题目链接 说实话挺喜欢soj的界面,简简单单,没有多余的东西hhh(但是简单到连内存限制,时间限制都看不到了. 题意是有个“奇葩”的主人公,吃饭要用三根筷子.两根短的一根长的. 现在给你n根筷子,要在 ...
- codeforces605A
Sorting Railway Cars CodeForces - 605A 一辆列车有N节车厢,编号为1...N(每节车厢编号都不同),并且他们的排列是混乱的.李老湿想要把这N节车厢重新排列为升序排 ...
- 51-node-1649齐头并进(最短路)
题意:中文题,没啥坑点: 解题思路:这道题一开始以为要跑两个最短路,后来发现不用,因为如果给定了铁路的线路,那么,公路一定是n个节点无向图的补图,所以,铁路和公路之间一定有一个是可以直接从1到n的,我 ...
- H.264编码原理以及I帧B帧P帧
前言 ----------------------- H264是新一代的编码标准,以高压缩高质量和支持多种网络的流媒体传输著称,在编码方面,我理解的他的理论依据是:参照一段时间内图像的统计结果表明,在 ...