1.原型

Javascript规定,每一个函数都有一个prototype对象属性,指向另一个对象(原型链上面的)。
prototype(对象属性)的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变(公用)的属性和方法,直接定义在prototype对象属性上。
prototype就是调用构造函数所创建的那个实例对象的原型(proto)。
prototype可以让所有对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中定义对象信息,而是可以直接将这些信息添加到原型中。

1.1访问原型

原型实际就是一个普通对象,继承Object类,有JavaScript自动创建并依附在每个函数中,
访问原型的三种方法:
obj.__proto__
obj.constructor.prototype
Object.getPrototypeOf(obj)//是一个静态函数,参数是实例对象,返回值是实例对象的原型对象
注意:obj是一个实例对象,constructor表示构造函数。
实例设计:

  1. var F = funciton() {}; //构造函数
  2. var obj= new F(); //实例化
  3. var Proto1 = obj.__proto__; //引用原型(注意,IE暂不支持)
  4. var Proto2 = obj.constructor.prototype; //引用原型
  5. var Proto3 = Object.getPrototypeOf(obj); //引用原型
  6. var Proto4 = F.prototype; //利用构造函数访问原型
  7. console.log(Proto1==Proto2); //ture

1.2设置原型

设置原型的三种方法
obj.__proto__=prototypeObj;
Object.setPrototypeOf(obj,prototypeObj);
Object.create(prototypeObj);
其中,obj表示一个实例对象,prototypeObj表示原型对象。注意,IE目前不支持前面两种方法。
实例设计:通过以上三种方法,为对象直接量设置原型;

  1. var proto = {
  2. name: "prototype"
  3. }; //原型对象
  4. var obj1 = {}; //普通对象直接量
  5. obj1.__proto__ = proto; //设置原型
  6. console.log(obj1.__proto__);
  7. var obj2 = {};
  8. Object.setPrototypeOf(obj2, proto); //设置原型
  9. console.log(obj2.name);
  10. var obj3 = Object.create(proto); //创建对象并设置原型
  11. console.log(obj3.name);

图片.png

1.3检测原型

使用isPrototypeOf方法可以判断该对象是否为参数对象的原型对象。isPrototypeOf()是一个原型方法,可以在每个实例对象上调用。
实例设计:

  1. //检测原型
  2. var F = function() {}; //构造函数
  3. var obj = new F(); //实例化
  4. var proto1 = Object.getPrototypeOf(obj); //引用原型
  5. console.log(proto1.isPrototypeOf(obj)); //true
  6. console.log(Object.getPrototypeOf(obj));

图片.png
也可以使用下面的代码检测不同类型的实例对象

  1. var proto2 = Object.prototype;
  2. console.log(proto2.isPrototypeOf({})); //true
  3. console.log(proto2.isPrototypeOf([])); //true
  4. console.log(proto2.isPrototypeOf(/ /)); //true
  5. console.log(proto2.isPrototypeOf(function() {})); //true
  6. console.log(proto2.isPrototypeOf(null)); //false

图片.png

1.4应用原型

原型对象可以被所有实例访问,而私有属性只能被当前实例访问。
实例设计
示例1:利用原型为对象设置默认值。当原型属性与私有属性同名是,删除私有属性之后,可以访问原型属性,即可以把原型属性值作为初始化默认值。

  1. //【示例1】利用原型为对象设置默认值。当原型属性与私有属性同名时,删除私有属性之后,可以访问原型属性,即可以把原型属性值作为初始化默认值。
  2. function p(x){ //构造函数
  3. if(x) //如果参数存在,则设置属性,该条件是关键
  4. this.x = x; //使用参数初始化私有属性x的值
  5. }
  6. p.prototype.x = 0; //利用原型属性,设置私有属性x的默认值
  7. var p1 = new p(); //实例化一个没有带参数的对象
  8. console.log(p1.x); //返回0,即显示私有属性的默认值
  9. var p2 = new p(1); //再次实例化,传递一个新的参数
  10. console.log(p2.x); //返回1,即显示私有属性的初始化值
  1. //【示例2】利用原型间接实现本地数据备份。把本地对象的数据完全赋值给原型对象,相当于为该对象定义一个副本,通俗地说就是备份对象。这样当对象属性被修改时,可以通过原型对象来恢复本地对象的初始值。
  2. function p(x){ //构造函数
  3. this.x = x;
  4. }
  5. p.prototype.backup = function(){ //原型方法,备份本地对象的数据到原型对象中
  6. for(var i in this){
  7. p.prototype[i] = this[i];
  8. }
  9. }
  10. var p1 = new p(1); //实例化对象
  11. p1.backup(); //备份实例对象中的数据
  12. p1.x =10; //改写本地对象的属性值
  13. console.log(p1.x) //返回10,说明属性值已经被改写
  14. p1 = p.prototype; //恢复备份
  15. console.log(p1.x) //返回1,说明对象的属性值已经被恢复
  1. //【示例3】利用原型还可以为对象属性设置“只读”特性,这在一定程序上可以避免对象内部数据被任意修改的尴尬。下面示例演示了如何根据平面上两点坐标来计算它们之间的距离。构造函数p用来设置定位点坐标,当传递两个参数值时,会返回以参数为坐标值的点,如果省略参数则默认点为原点(0,0)。而在构造函数l中通过传递的两点坐标对象,技算它们的距离。
  2. function p(x,y){ //求坐标点构造函数
  3. if(x) this.x =x; //初始x轴值
  4. if(y) this.y = y; //初始y轴值
  5. p.prototype.x =0; //默认x轴值
  6. p.prototype.y = 0; //默认y轴值
  7. }
  8. function l(a,b){ //求两点距离构造函数
  9. var a = a; //参数私有化
  10. var b = b; //参数私有化
  11. var w = function(){ //计算x轴距离,返回对函数引用
  12. return Math.abs(a.x - b.x);
  13. }
  14. var h = function(){ //计算y轴距离,返回对函数引用
  15. return Math.abs(a.y - b.y);
  16. }
  17. this.length = function(){ //计算两点距离,调用私有方法w()和h()
  18. return Math.sqrt(w()*w() + h()*h());
  19. }
  20. this.b = function(){ //获取起点坐标对象
  21. return a;
  22. }
  23. this.e = function(){ //获取终点坐标对象
  24. return b;
  25. }
  26. }
  27. var p1 = new p(1,2); //实例化p构造函数,声明一个点
  28. var p2 = new p(10,20); //实例化p构造函数,声明另一个点
  29. var l1 = new l(p1,p2); //实例化l构造函数,传递两点对象
  30. console.log(l1.length()) //返回20.12461179749811,计算两点距离
  31. l1.b().x = 50; //不经意改动方法b()的一个属性为50
  32. console.log(l1.length()) //返回43.86342439892262,说明影响两点距离值

…….
2.原型链
在JavaScript中,实例对象在读取属性值时,总是先检查私有属性,如果存在,则会返回私有属性值,否则就会检索prototype原型,如果找到同名属性,则返回prototype原型的属性值。
prototype原型允许引用其他对象。如果在prototype原型中没有找到指定的属性,则JavaScript将会根据引用关系,继续检索prototype原型对象的prototype原型,以此类推。
实例设计

  1. //示例1,下面的示例演示了对象属性查找原型的基本方法和属性
  2. function a(x) {
  3. this.x = x;
  4. } //构造函数
  5. a.prototype.x = 0; //原型属性x的值为0
  6. function b(x) {
  7. this.x = x; //构造函数b
  8. }
  9. b.prototype = new a(1); //原型对象为构造函数a的实例
  10. function c(x) {
  11. this.x = x; //构造函数c
  12. }
  13. c.prototype = new b(2); //原型对象为构造函数b的实例
  14. var d = new c(3); //实例化构造函数c
  15. console.log(d.x); //调用实例对象d的私有属性,返回值为3
  16. delete d.x; //删除实例对象的私有属性x
  17. console.log(d.x); //调用实例对象d的属性,返回值为2
  18. delete c.prototype.x; //删除c类原型属性x
  19. console.log(d.x); //调用实例对象d的属性x,返回值为1
  20. delete b.prototype.x; //删除b类原型属性x
  21. console.log(d.x); //返回值为0

图片.png