基本概念
对象:对象就是一个整体,对外提供一个整体。
面向对象:使用对象时,只关注对象提供的功能,不关注其内部的细节。
三个特点(类C++):封装、继承、多态
一些概念区别
1、方法与函数
方法:obj.fn = function(){}
函数:function fn(){}
其中函数 function fn(){} 相当于 window.fn = function(){}
2、类与对象
类:不具备实际的功能,只能用来构造对象
对象:真正有功能的东西,被类给构造出来的
封装构造函数(工厂模式)
以person为对象举例 (有两个属性 name sex)

1 <script> 2 function CreatePerson(name , sex){ 3 var obj = new Object(); 4 5 //添加属性 6 obj.name = name; 7 obj.sex = sex; 8 9 //添加方法 10 obj.showName = function () { 11 alert(this.name); 12 }; 13 obj.showSex = function () { 14 alert(this.sex); 15 }; 16 return obj; 17 } 18 19 var p1 = CreatePerson('leo' , 'male'); 20 var p2 = CreatePerson('shawn' , 'male'); 21 p1.showName(); 22 p1.showSex(); 23 24 alert(p1.showName == p2.showName); 25 </script>
以这样的方式(其实就是创建一个函数,然后实例对象利用函数传参来实现,这样做的话实例之间是没有什么内在联系的)来构造对象会有两个问题:
1、没有用到new方法
2、每个被创建的对象都有一套自己的方法(例如上述p1.showName()、p2.showName()),而这些方法的实现是一模一样的,这样就造成了资源的极度浪费
解决方案
针对第一个问题,做出的改进如下

1 function CreatePerson(name , sex){ 2 3 //相当于这边有 4 // var this = new Object(); 5 //添加属性 6 this.name = name; 7 this.sex = sex; 8 9 //添加方法 10 this.showName = function () { 11 alert(this.name); 12 }; 13 this.showSex = function () { 14 alert(this.sex); 15 }; 16 //这边有return this; 17 }
这个时候生成的实例对象会自动包含一个constructor属性,指向它们的构造函数
当然还可以使用instanceof来验证实例对象是否属于原型对象
针对第二个问题,我们可以使用prototype(原型),Javascript规定,每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。这很像CSS中的class,可以给一堆对象加上相同的属性或方法。主要是用来添加一些系统不支持的方法或函数

1 <script> 2 function CreatePerson(name , sex){ 3 //添加属性 4 this.name = name; 5 this.sex = sex; 6 } 7 //添加共用方法 8 CreatePerson.prototype.showName = function () { 9 alert(this.name); 10 }; 11 CreatePerson.prototype.showSex = function () { 12 alert(this.sex); 13 }; 14 15 var p1 = new CreatePerson('leo' , 'male'); 16 var p2 = new CreatePerson('shawn' , 'male'); 17 p1.showName(); 18 p1.showSex(); 19 20 alert(p1.showName == p2.showName); 21 </script>
这个时候我们会发现最后的输出是true,这时候用的都是同一个内存地址,指向了prototype对象,内存的使用效率就变高。
最后关于一个优先级的问题

1 <script> 2 Array.prototype.a = 12; //给Array类添加公共属性a = 12; 3 var arr = [1,2,3]; 4 alert(arr.a); //12 5 6 arr.a = 5; //给由Array类所创造的对象arr添加重名属性a 7 alert(arr.a); // 5 8 9 delete arr.a; //删除arr对象的a属性 10 alert(arr.a); //12 11 </script>
我们会发现这和CSS中内部样式和行间样式很相像,prototype添加的属性相当于一个内部样式 ,而对象的重名属性相当于行间样式 , 所以重名时对象的属性优先级肯定是高于prototype所添加的属性的。