您的位置:首页 > Web前端

前端基础知识总结-原型与原型链

2018-03-29 11:53 696 查看
原型与原型链
封装(点击打开链接)构造函数的继承(点击打开链接)非构造函数的继承(点击打开链接
Javascript规定,每一个构造函数都有一个
prototype
属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。
这意味着,我们可以把那些不变的属性和方法,直接定义在
prototype
对象上。
function Cat(name,color){    this.name = name;    this.color = color;  }  Cat.prototype.type = "猫科动物";  Cat.prototype.eat = function(){alert("吃老鼠")};
然后,生成实例。
var cat1 = new Cat("大毛","黄色");  var cat2 = new Cat("二毛","黑色");  alert(cat1.type); // 猫科动物  cat1.eat(); // 吃老鼠
这时所有实例的
type
属性和
eat()
方法,其实都是同一个内存地址,指向
prototype
对象,因此就提高了运行效率。
alert(cat1.eat == cat2.eat); //true
Prototype模式的验证方法
为了配合
prototype
属性,Javascript定义了一些辅助方法,帮助我们使用它。,
isPrototypeOf()
这个方法用来判断,某个
proptotype
对象和某个实例之间的关系。
alert(Cat.prototype.isPrototypeOf(cat1)); //truealert(Cat.prototype.isPrototypeOf(cat2)); //true
hasOwnProperty()
每个实例对象都有一个
hasOwnProperty()
方法,用来判断某一个属性到底是本地属性,还是继承自
prototype
对象的属性。
alert(cat1.hasOwnProperty("name")); // truealert(cat1.hasOwnProperty("type")); // false
in运算符
in
运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。
alert("name" in cat1); // truealert("type" in cat1); // true
in
运算符还可以用来遍历某个对象的所有属性。
for(var prop in cat1) { alert("cat1["+prop+"]="+cat1[prop]); }
继承
function Animal(){    this.species = "动物";}function Cat(name,color){    this.name = name;    this.color = color;}
 构造函数绑定
使用call或apply方法,将父对象的构造函数绑定在子对象上,即在子对象构造函数中加一行:
function Cat(name,color){Animal.apply(this, arguments);//Animal.call(this);(两种写法都可以输出)    this.name = name;    this.color = color;  }  var cat1 = new Cat("大毛","黄色");  alert(cat1.species); // 动物
prototype模式
第二种方法更常见,使用prototype属性。
function Action() {} 
Action.prototype.Cando=function(){  
    console.log("saddd"); 
}
 function ben(){} 
ben.prototype=new Action();
 var aas=new ben(); 
console.log(aas); 
浅拷贝
var Chinese = {
    nation:'中国'
  };
var Doctor ={
    career:'医生'

  }
这两个对象都是普通对象,不是构造函数,无法使用构造函数方法实现"继承"。

除了使用"prototype链"以外,还有另一种思路:把父对象的属性,全部拷贝给子对象,也能实现继承。
function extendCopy(p) {    var c = {};    for (var i in p) { 
      c[i] = p[i];
    }    c.uber = p;    return c;
  }
var Doctor = extendCopy(Chinese);  Doctor.career = '医生';  alert(Doctor.nation); // 中国
这样的拷贝有一个问题。那就是,如果父对象的属性等于数组或另一个对象,那么实际上,子对象获得的只是一个内存地址,而不是真正拷贝,因此存在父对象被篡改的可能。
现在给Chinese添加一个"出生地"属性,它的值是一个数组
Chinese.birthPlaces = ['北京','上海','香港'];

通过extendCopy()函数,Doctor继承了Chinese。

var Doctor = extendCopy(Chinese);

我们为Doctor的"出生地"添加一个城市:

Doctor.birthPlaces.push('厦门');

Chinese的"出生地"也被改掉了!

alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门alert(Chinese.birthPlaces); //北京, 上海, 香港, 厦门extendCopy()只是拷贝基本类型的数据,我们把这种拷贝叫做"浅拷贝"。这是早期jQuery实现继承的方式。

深拷贝
就是能够实现真正意义上的数组和对象的拷贝。它的实现并不难,只要递归调用"浅拷贝"就行了。
function deepCopy(p, c) {    var c = c || {};    for (var i in p) {      if (typeof p[i] === 'object') {        c[i] = (p[i].constructor === Array) ? [] : {};        deepCopy(p[i], c[i]);      } else {         c[i] = p[i];      }
    }    return c;
  }

var Doctor = deepCopy(Chinese);
Chinese.birthPlaces = ['北京','上海','香港'];

Doctor.birthPlaces.push('厦门');

jQuery库使用的就是这种继承方法。

alert(Doctor.birthPlaces); //北京, 上海, 香港, 厦门  alert(Chinese.birthPlaces); //北京, 上海, 香港
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: