海军 发表于 2016-1-8 23:56

【笔记】深入理解Javascript面向对象编程-二

本帖最后由 奋斗丶小Z 于 2016-1-9 00:10 编辑

二:理解原型域链的概念
原型的优点是能够以对象结构为载体,创建大量的实列,这些实列能共享原型中的成员(属性和方法);同时也可以使用原型实现面向对象中的继承机制~ 如下代码:下面我们来看这个构造函数AA和构造函数BB,当BB.prototype = new AA(11);执行这个的时候,那么B就继承与A,B中的原型就有x的属性值为11
function AA(x){    this.x = x;}function BB(x) {    this.x = x;}BB.prototype = new AA(11);console.log(BB.prototype.x); //11
// 我们再来理解原型继承和原型链的概念,代码如下,都有注释function A(x) {    this.x = x;}// 在A的原型上定义一个属性x = 0A.prototype.x = 0;function B(x) {    this.x = x;}B.prototype = new A(1);实列化A new A(1)的时候 在A函数内this.x =1, B.prototype = new A(1);B.prototype 是A的实列 也就是B继承于A, 即B.prototype.x = 1; 如下代码:console.log(B.prototype.x); // 1// 定义C的构造函数function C(x) {    this.x = x;}C.prototype = new B(2);C.prototype = new B(2); 也就是C.prototype 是B的实列,C继承于B;那么new B(2)的时候 在B的构造函数内 this.x = 2;那么 C的原型上会有一个属性x =2 即C.prototype.x = 2; 如下代码:
console.log(C.prototype.x); // 2下面是实列化 var d = new C(3); 实列化C的构造函数时候,那么在C的构造函数内this.x = 3; 因此如下打印实列化后的d.x = 3;如下代码:
var d = new C(3);console.log(d.x); // 3删除d.x 再访问d.x的时候 本实列对象被删掉,只能从原型上去查找;由于C.prototype = new B(2); 也就是C继承于B,因此C的原型也有x = 2;即C.prototype.x = 2; 如下代码:
delete d.x;console.log(d.x);//2删除C.prototype.x后,我们从上面代码知道,C是继承于B的,自身的原型被删掉后,会去查找父元素的原型链,因此在B的原型上找到x =1; 如下代码:
delete C.prototype.x;console.log(d.x);// 1当删除B的原型属性x后,由于B是继承于A的,因此会从父元素的原型链上查找A原型上是否有x的属性,如果有的话,就返回,否则看A是否有继承,没有继承的话,继续往Object上去查找,如果没有找到就返回undefined 因此当删除B的原型x后,delete B.prototype.x; 打印出A上的原型x=0; 如下代码:
delete B.prototype.x;console.log(d.x);// 0
// 继续删除A的原型x后 结果没有找到,就返回undefined了;delete A.prototype.x;console.log(d.x);// undefined在javascript中,一切都是对象,Function和Object都是函数的实列;构造函数的父原型指向于Function原型,Function.prototype的父原型指向与Object的原型,Object的父原型也指向与Function原型,Object.prototype是所有原型的顶层;
如下代码:Function.prototype.a = function(){    console.log("我是父原型Function");}Object.prototype.a = function(){    console.log("我是 父原型Object");}function A(){    this.a = "a";}A.prototype = {    B: function(){      console.log("b");    }}// Function 和 Object都是函数的实列 如下:console.log(A instanceof Function);// trueconsole.log(A instanceof Object); // true
// A.prototype是一个对象,它是Object的实列,但不是Function的实列console.log(A.prototype instanceof Function); // falseconsole.log(A.prototype instanceof Object); // true
// Function是Object的实列 同是Object也是Function的实列console.log(Function instanceof Object);   // trueconsole.log(Object instanceof Function); // true
/* * Function.prototype是Object的实列 但是Object.prototype不是Function的实列 * 说明Object.prototype是所有父原型的顶层 */console.log(Function.prototype instanceof Object);//trueconsole.log(Object.prototype instanceof Function);// false三:理解原型继承机制
构造函数都有一个指针指向原型,Object.prototype是所有原型对象的顶层,比如如下代码:
var obj = {};Object.prototype.name = "tugenhua";console.log(obj.name); // tugenhua给Object.prototype 定义一个属性,通过字面量构建的对象的话,都会从父类那边获取Object.prototype的属性;
从上面代码我们知道,原型继承的方法是:假如A需要继承于B,那么A.prototype(A的原型) = new B()(作为B的实列) 即可实现A继承于B; 因此我们下面可以初始化一个空的构造函数;然后把对象赋值给构造函数的原型,然后返回该构造函数的实列; 即可实现继承; 如下代码:
if(typeof Object.create !== 'function') {    Object.create = function(o) {      var F = new Function();      F.prototype = o;      return new F();    }}var a = {    name: 'longen',    getName: function(){      return this.name;    }};var b = {};b = Object.create(a);console.log(typeof b); //objectconsole.log(b.name);   // longenconsole.log(b.getName()); // longen如上代码:我们先检测Object是否已经有Object.create该方法;如果没有的话就创建一个; 该方法内创建一个空的构造器,把参数对象传递给构造函数的原型,最后返回该构造函数的实列,就实现了继承方式;如上测试代码:先定义一个a对象,有成员属性name=’longen’,还有一个getName()方法;最后返回该name属性; 然后定义一个b空对象,使用Object.create(a);把a对象继承给b对象,因此b对象也有属性name和成员方法getName();
理解原型查找原理:对象查找先在该构造函数内查找对应的属性,如果该对象没有该属性的话,
那么javascript会试着从该原型上去查找,如果原型对象中也没有该属性的话,那么它们会从原型中的原型去查找,直到查找的Object.prototype也没有该属性的话,那么就会返回undefined;因此我们想要仅在该对象内查找的话,为了提高性能,我们可以使用hasOwnProperty()来判断该对象内有没有该属性,如果有的话,就执行代码(使用for-in循环查找):如下:
var obj = {    "name":'tugenhua',    "age":'28'};// 使用for-in循环for(var i in obj) {    if(obj.hasOwnProperty(i)) {      console.log(obj); //tugenhua 28    }}如上使用for-in循环查找对象里面的属性,但是我们需要明白的是:for-in循环查找对象的属性,它是不保证顺序的,for-in循环和for循环;最本质的区别是:for循环是有顺序的,for-in循环遍历对象是无序的,因此我们如果需要对象保证顺序的话,可以把对象转换为数组来,然后再使用for循环遍历即可;
页: [1]
查看完整版本: 【笔记】深入理解Javascript面向对象编程-二