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

原型与原型链
封装(点击打开链接构造函数的继承(点击打开链接非构造函数的继承(点击打开链接
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)); //true

alert(Cat.prototype.isPrototypeOf(cat2)); //true

hasOwnProperty()
每个实例对象都有一个hasOwnProperty()方法,用来判断某一个属性到底是本地属性,还是继承自prototype对象的属性。

alert(cat1.hasOwnProperty("name")); // true

alert(cat1.hasOwnProperty("type")); // false

in运算符
in运算符可以用来判断,某个实例是否含有某个属性,不管是不是本地属性。

alert("name" in cat1); // true

alert("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); //北京, 上海, 香港




猜你喜欢

转载自blog.csdn.net/chenacxz/article/details/79738838