原本打算也写一个JavaScript学习笔记的系列,不过因为笔者不太想买大部头的js数据,和网上的资料也很多,因此js系列就打算写到了算了了。编程
要理解JavaScript就要理解其原型,首先咱们先区分一下JavaScript中的两种不一样方式建立的函数;框架
1 function foo1(){} 2 console.log(foo1.prototype); 3 console.log(foo1.__proto__); 4 5 var foo2 = function() {} 6 console.log(foo2.prototype); 7 console.log(foo2.__proto__);
这里有两个属性prototype和__proto__,咱们来看他们分别指向什么。函数
咱们在看看foo1.prototype包含的属性:学习
1 function foo(){} 2 console.log(foo.prototype.__proto__ === Object.prototype);//true
能够看见,原型对象的__proto__指向其父级对象的prototype;this
1 function foo(){} 2 var a = new foo(); 3 console.log(a.prototype);//undefined 4 console.log(a.__proto__);//Object
经过输出咱们能够发现,经过new获得的对象,prototype属性是空的,而__proto__则被赋予了一个对象,看下面的代码:spa
1 function foo(){} 2 var a = new foo(); 3 console.log(a.__proto__ === foo.prototype);//true
js将foo的原型属性赋予了用new关键字建立的a对象;prototype
咱们看看使用new关键字js为咱们作了什么操做;code
好比下面的代码:对象
var a = new foo();
能够理解为调用了下面的代码:blog
1 var a={};//也就是说,初始化一个对象a; 2 a.__proto__=foo.prototype;//赋值原型链; 3 foo.call(a);//也就是说构造a,也能够称之为初始化a;
咱们再来看看js的原型继承,js中的继承是经过原型链来体现的,简单的说,当咱们调用一个属性时(方法在js中也是以属性的形式存在的),会先查找自身是否有该属性,若是没有则查找原型上是否存在该属性,若是仍是没有,则查找原型上的__proto__(即父类的原型)里是否有该属性,若是没有则一致搜索到最顶级(即Object的原型),找到则返回该属性的值,找不到则返回undefined。
咱们看下下面的代码:
1 var foo = function(){ 2 var a = 0; 3 this.a = 1; 4 }; 5 foo.prototype.a = 2; 6 foo.prototype.b = "b"; 7 console.log(foo.a);//undefined 8 foo.a = 4; 9 foo.c = 5; 10 console.log(foo.a);//4 11 12 var obj = new foo(); 13 console.log(obj.a);//1 14 console.log(obj.b);//b 15 console.log(obj.c);//undefined
咱们分析一下:
若是按面向对象的思惟来看,能够这么理解:
1 //建立类 Foo,按通常的规则类名首字母大写 2 var Foo = function(){ 3 this.a = 1;//建立一个公开的属性a 4 }; 5 //建立一个公开的方法 add 6 Foo.prototype.add = function(a, b){ 7 return a + b; 8 } 9 //建立一个静态变量 num 10 Foo.num = 100; 11 //建立一个静态方法 subtract 12 Foo.subtract = function(a, b){ 13 return a - b; 14 } 15 16 //调用静态属性及方法 17 console.log(Foo.subtract(Foo.num, 11));//89 18 //调用对象属性及方法 19 var obj = new Foo(); 20 console.log(obj.add(obj.a, Foo.num));//101
目前咱们知道了使用js来模拟编写一个类的方法,即如何封装咱们知道了,可是面向对象编程还有两个重要的特性:继承和多态;
可是因为js是没有类型的概念的,因此多态这个特性咱们能够忽略,那么js如何使用原型来实现类继承的效果呢?
实际上,有不少方法能够实现类继承的效果,或者复杂,或者简单,接下来的两篇文章,我会介绍两种js实现类继承的方法:
以上方式你们能够二选一,固然也可使用别的方法;
最后说一下,最新的js标准ES6中,已经支持class关键字来定义类了,不过在ES6还没有普及的这几年,为了兼容更多的用户仍是乖乖使用老的方式吧;