本来打算也写一个JavaScript学习笔记的系列,不过由于笔者不太想买大部头的js数据,和网上的资料也不少,所以js系列就打算写到了算了了。

要理解JavaScript就要理解其原型,首先我们先区分一下JavaScript中的两种不同方式创建的函数;

直接定义得到的函数

 function foo1(){}
console.log(foo1.prototype);
console.log(foo1.__proto__); var foo2 = function() {}
console.log(foo2.prototype);
console.log(foo2.__proto__);

这里有两个属性prototype和__proto__,我们来看他们分别指向什么。

  1. prototype:指向函数原型;
  2. __proto__:指向一个匿名的空方法;

我们在看看foo1.prototype包含的属性:

  1. constructor(指向函数本身)
  2. __proto__(指向父级对象的prototype),可以看下面的验证代码:
 function foo(){}
console.log(foo.prototype.__proto__ === Object.prototype);//true

可以看见,原型对象的__proto__指向其父级对象的prototype;

通过new关键字创建得到的对象

 function foo(){}
var a = new foo();
console.log(a.prototype);//undefined
console.log(a.__proto__);//Object

通过输出我们可以发现,通过new得到的对象,prototype属性是空的,而__proto__则被赋予了一个对象,看下面的代码:

 function foo(){}
var a = new foo();
console.log(a.__proto__ === foo.prototype);//true

js将foo的原型属性赋予了用new关键字创建的a对象;

我们看看使用new关键字js为我们做了什么操作;

比如下面的代码:

var a = new foo();

可以理解为调用了下面的代码:

 var a={};//也就是说,初始化一个对象a;
a.__proto__=foo.prototype;//赋值原型链;
foo.call(a);//也就是说构造a,也可以称之为初始化a;

原型继承

我们再来看看js的原型继承,js中的继承是通过原型链来体现的,简单的说,当我们调用一个属性时(方法在js中也是以属性的形式存在的),会先查找自身是否有该属性,如果没有则查找原型上是否存在该属性,如果还是没有,则查找原型上的__proto__(即父类的原型)里是否有该属性,如果没有则一致搜索到最顶级(即Object的原型),找到则返回该属性的值,找不到则返回undefined。

我们看下下面的代码:

 var foo = function(){
var a = 0;
this.a = 1;
};
foo.prototype.a = 2;
foo.prototype.b = "b";
console.log(foo.a);//undefined
foo.a = 4;
foo.c = 5;
console.log(foo.a);// var obj = new foo();
console.log(obj.a);//
console.log(obj.b);//b
console.log(obj.c);//undefined

我们分析一下:

  1. 函数中的var a = 0;是一个作用域在该函数中的临时变量,函数外部是不能访问的;
  2. 函数中的this.a = 1;定义的变量只能在使用new关键字创建的对象中才能访问到;
  3. 直接在foo上面赋值的a,也只能使用foo.a可以访问到,使用new关键字创建的对象不能访问到;
  4. 如果没有在函数内部使用this.b = 1;来创建的属性,会去其原型对象prototype上寻找,找到则返回了1,相反,a在函数内部指定了,则可以访问到;
  5. 在foo上直接定义的c,使用new创建的对象不能访问到;

如果按面向对象的思维来看,可以这么理解:

 //创建类 Foo,按一般的规则类名首字母大写
var Foo = function(){
this.a = 1;//创建一个公开的属性a
};
//创建一个公开的方法 add
Foo.prototype.add = function(a, b){
return a + b;
}
//创建一个静态变量 num
Foo.num = 100;
//创建一个静态方法 subtract
Foo.subtract = function(a, b){
return a - b;
} //调用静态属性及方法
console.log(Foo.subtract(Foo.num, 11));//
//调用对象属性及方法
var obj = new Foo();
console.log(obj.add(obj.a, Foo.num));//

实现类继承

目前我们知道了使用js来模拟编写一个类的方法,即如何封装我们知道了,但是面向对象编程还有两个重要的特性:继承和多态;

但是由于js是没有类型的概念的,所以多态这个特性我们可以忽略,那么js如何使用原型来实现类继承的效果呢?

实际上,有很多方法可以实现类继承的效果,或者复杂,或者简单,接下来的两篇文章,我会介绍两种js实现类继承的方法:

  1. TypeScript的实现方式,由微软维护的js的超集,实现了静态语言的大部分特性,学习TypeScript编译出的JavaScript的实现方式,微软都这么实现了,咱们就照搬就行了;
  2. Cocos2dx-js的实现方式,作为一款成熟的游戏框架,cocos的实现不同于微软的ts的实现,但也一种值得学习的类实现的方式;

以上方式大家可以二选一,当然也可以使用别的方法;

最后说一下,最新的js标准ES6中,已经支持class关键字来定义类了,不过在ES6尚未普及的这几年,为了兼容更多的用户还是乖乖使用老的方式吧;

认识JavaScript的原型的更多相关文章

  1. Javascript的原型链图

    90%的前端或者js程序员或者老师们对Javascript懂得不比这个多 给手机看的 但是这个图里的所有褐色单向箭头链就是Javascript的原型链(颜色标注对理解js原型链很关键) 这图中的各个_ ...

  2. 深入理解JavaScript系列:史上最清晰的JavaScript的原型讲解

    一说起JavaScript就要谈的几个问题,原型就是其中的一个.说了句大话,史上最清晰.本来是想按照大纲式的行文写一下,但写到后边感觉其实就一个概念,没有什么条理性,所以下面就简单按照概念解释的模式谈 ...

  3. 【面试必备】javascript的原型和继承

    原型.闭包.作用域等知识可以说是js中面试必考的东西,通过你理解的深度也就能衡量出你基本功是否扎实.今天来复习一下javascript的原型和继承,虽说是老生常谈的话题,但对于这些知识,自己亲手写一遍 ...

  4. javascript进阶-原型prototype

    一.javascript原型认识 很多编程语言都有类的概念,我们可以拿原型和类进行比较,看看它们之间的区别以及相同点在哪里. 1.类:类是一个具体事物的抽象所以类是一个抽象的东西,在面向对象中类可以用 ...

  5. 理解JavaScript 的原型属性

    1.原型继承 面向对象编程可以通过很多途径实现.其他的语言,比如 Java,使用基于类的模型实现: 类及对象实例区别对待.但在 JavaScript 中没有类的概念,取而代之的是一切皆对象.JavaS ...

  6. JavaScript - 基于原型的面向对象

    JavaScript - 基于原型的面向对象 1. 引言 JavaScript 是一种基于原型的面向对象语言,而不是基于类的!!! 基于类的面向对象语言,比如 Java,是构建在两个不同实体的概念之上 ...

  7. JavaScript的原型继承

    JavaScript是一门面向对象的语言.在JavaScript中有一句很经典的话,万物皆对象.既然是面向对象的,那就有面向对象的三大特征:封装.继承.多态.这里讲的是JavaScript的继承,其他 ...

  8. javaScript系列 [04]-javaScript的原型链

    [04]-javaScript的原型链 本文旨在花很少的篇幅讲清楚JavaScript语言中的原型链结构,很多朋友认为JavaScript中的原型链复杂难懂,其实不然,它们就像树上的一串猴子. 1.1 ...

  9. JavaScript prototype原型和原型链详解

    用过JavaScript的同学们肯定都对prototype如雷贯耳,但是这究竟是个什么东西却让初学者莫衷一是,只知道函数都会有一个prototype属性,可以为其添加函数供实例访问,其它的就不清楚了, ...

  10. Javascript的原型继承,说清楚

    一直以来对Javascript的原型.原型链.继承等东西都只是会用和了解,但没有深入去理解这门语言关于继承这方面的本质和特点.闲暇之余做的理解和总结,欢迎各位朋友一起讨论. 本文本主要从两段代码的区别 ...

随机推荐

  1. ubuntu下安装mysql及外网访问设置

    这么多年一直是mssql或者Oracle,mysql基本没用过,借着.net即将跨平台之际,也mysql一把.windows安装基本没啥难度,然后就是试了把linux下...结果坑不少,由于linux ...

  2. 使用Java VisualVM监控远程JVM

    我们经常需要对我们的开发的软件做各种测试, 软件对系统资源的使用情况更是不可少, 目前有多个监控工具, 相比JProfiler对系统资源尤其是内存的消耗是非常庞大,JDK1.6开始自带的VisualV ...

  3. 【 D3.js 高级系列 — 9.0 】 交互式提示框

    一般来说,图表中不宜存在过多文字.但是,有时需要一些文字来描述某些图形元素.那么,可以实现一种交互:当用户鼠标滑到某图形元素时,出现一个提示框,里面写有描述文字.这是一种简单.普遍的交互式,几乎适用于 ...

  4. fmri当前相关软件工具整理

    1.spm; 2.afni; 3.fsl; 4.drtools; 5.prtools; 6.phycaa+; 7.cca-fmri;

  5. 深入学习Oracle分区表及分区索引

    关于分区表和分区索引(About Partitioned Tables and Indexes)对于10gR2而言,基本上可以分成几类: •       Range(范围)分区 •       Has ...

  6. 自动FTP的小脚本

    自动FTP的小脚本 使用以下脚本,可以实现自动FTP,将你需要的文件传送到需要的地方,或者将需要的文件从某个地方抓取下来. cd /PATH_YOU_WANT_TO_UPLOAD(DOWNLOAD) ...

  7. andeoid学习笔记七

    Android中Broadcast的Intent大全 Api Level 3:(SDK 1.5) android.bluetooth.a2dp.intent.action.SINK_STATE_CHA ...

  8. 修改Oracle 表空间名称 tablespace name

    修改表空间名称步骤如下: 1. 使用oracle用户登录执行 $sqlplus / as sysdba 2. 执行修改表空间命令如下 SQL> alter tablespace  TEST re ...

  9. 使用Visual Studio 2013对windows应用商店应用进行编码的UI测试

    之前进行了一次实验,实验内容是对windows应用商店应用进行编码的UI测试,下面对实验步骤进行详细说明: 1.为 Windows 应用商店应用创建新编码的 UI 测试项目,选择Visual C##→ ...

  10. 【转载】epoll的使用

    select,poll,epoll简介 select select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理.这样所带来的缺点是: 1 单个进程可监视的fd数量被限制 2 需要维 ...