吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2558|回复: 0
收起左侧

[其他转载] 【笔记】深入理解Javascript面向对象编程-二

[复制链接]
海军 发表于 2016-1-8 23:56
本帖最后由 奋斗丶小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 = 0

A.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);  // true

console.log(A instanceof Object); // true


// A.prototype是一个对象,它是Object的实列,但不是Function的实列

console.log(A.prototype instanceof Function); // false

console.log(A.prototype instanceof Object); // true


// Function是Object的实列 同是Object也是Function的实列

console.log(Function instanceof Object);   // true

console.log(Object instanceof Function); // true


/*

* Function.prototype是Object的实列 但是Object.prototype不是Function的实列

* 说明Object.prototype是所有父原型的顶层

*/

console.log(Function.prototype instanceof Object);  //true

console.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); //object

console.log(b.name);   // longen

console.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循环遍历即可;

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-15 13:29

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表