# oo

##创建对象

1. 原型、构造函数、实例之间的关系

* 原型的construct->构造函数;调用isPrototypeOf(obj)方法可以判定和实例的关系;
 * 构造函数的prototype->原型;
 * 实例的__proto__ ->原型(仅在chrome,safari,Firefox中存在,而共有的是[[prototype]]);用getPrototypeOf()方法可以返回[[prototype]]的值;
 * 构造函数后构造函数的‘子类’new产生一个实例,可以用instanceOf 操作符来检测构造函数是否出现在原型链上。

2. 说明:

* 一个函数在声明之后就会有prototype对象,对象的constructor属性所存放的指针指向该函数。
 * 对原型进行赋值,就让这个prototype中的指针指向了一个新的对象,里面的constructor属性自然会丢失。如果把父类的值赋给了它,那么这个constructor就是父类实例的值。父类实例并没有这个属性,于是继承父类的原型中的constructor。所以,子类构造函数的(this.constructor)的值通过这样的步骤获得:
 
    子类实例(没有)--子类原型 (没有)--父类原型(有,为父类构造函数)

3. new关键字的理解

new的作用就是新建一个作用域,将this指向该作用域,然后执行函数中的代码。不用new关键字,那么this将指向globle对象,在浏览器中是window对象。

4. 检测对象和属性的关系
 
(1)

* in操作符 能够访问该属性
 * hasOwnProperty() 存在实例中
 * !obj.hasOwnProperty() && in 存在原型中

(2)

* for-in循环 枚举出 包含实例中的属性和原型中 可枚举的属性;
 * Object.keys(obj) 返回一个数组 可枚举的实例属性;
 * object.getOwnPropertyNames(obj) 得到所有实例属性,无论是否可以枚举;

##实现继承

1. 原型链继承

2. 借用构造函数(又叫伪造对象,对象冒充法,经典继承等)

3. 组合继承(又叫伪经典继承)

function Anm(name,age) {
            this.name = name;
            this.age = age;
        }
        Anm.prototype.sayBye = function () {
            console.log(this.name + ' say bye to you!');
        };
        function Dog(food, name, age) {
            //从父类中,通过call或apply方法继承属性
            Anm.call(this, name, age);
            this.food = food;
        }
        //子类通过设置原型等于父类的一个实例的方式,继承方法
        Dog.prototype = new Anm();
        Dog.prototype.constructor = Dog;
        Dog.prototype.sayHello = function() {
            console.log(this.name + ' say hello to me!')
        };
        dog1 = new Dog('shit', '小黄狗', 15);
        console.log(dog1);    //{name: "小黄狗", age: 15, food: "shit", constructor: function, sayHello: function…}
        dog1.sayBye();    //小黄狗 say bye to you!
        dog1.sayHello();    //小黄狗 say hello to me!

这种继承,能够让子类产生的实例拥有自己的属性,又可以从父类的原型上面继承得到公用的方法。所以成为javascript中最常用的继承模式。

4. 原型式继承

function Anm(klass) {
            this.klass = klass;
        }
        var dog1 = Object.create(gou, {
            name: {
                configurable: true,
                enumerable: true,
                writable: true,
                value: '小黄'
            },
            birthyear: {
                value: 2012
            },
            age: {
                get: function () {
                    var thisTime = new Date();
                    return thisTime.getFullYear() - this.birthyear;
                }
            }
        });
        console.log('修改前的对象');
        console.log(dog1);  //Object {name: "小黄", birthyear: 2012, age: 3, klass: "狗狗"}
        dog1.name = '小李';
        dog1.birthyear = 2010;
        console.log('修改后的对象');  //Object {name: "xiaoli", birthyear: 2012, age: 3, klass: "狗狗"}
        console.log(dog1);

Object.create()方法接受两个参数,第一个是作为原型的对象,第二个是为新队想定义额外属性的对象,以JSON格式,每一个要新增的属性都是该对象中一个属性,它的值也是一个描述符对象。

属性有数据属性(如上面的name和birthyear)和访问器属性(如上面的age),如果只写入一个特性,其余特性的值将会被设置为false。所以上面的birthyear是无法改动的。
    
    这种方式可以在指向让一个对象与另一个对象保持类似的情况下使用,不用去进行构造函数的创建。

5. 寄生式继承

上面的Object.create()方法额可以只创第一个参数,然后在对返回的函数添加属性,再把这整个过程封装起来,这种方式叫作寄生式继承。
    
6. 寄生组合式继承

子类的原型在Dog.prototype = new Anm()过程中,为它添加了Anm中属性klass(值为undifiend),同时Dog构造函数中,同样为实例添加了klass,相当于在原型和实例中都创造了属性。如果属性很多的话,这是一种浪费。如果能够不让子类的原型产生这些属性,直接让他的[[prototype]]指向父类的原型的话,那么就能够继承父类的方法了。
    我们先封装一个方法:

function inheriyPrototype(subType, superType) {
            var newPrototype = Object.create(superType.prototype);
            subType.prototype = newPrototype;
            newPrototype.constructor = subType; //重写了subType.prototype后丢失了自己的constructor,这里进行补写
        }

这个方法让子类不通过父类的实例赋值,而是让它的[[prototype]]直接指向父类的实例。
    
    实际上,这个子类的原型是一个空函数创建的,这个空函数的原型等于父类的原型。所以就让这个空函数的实例只有一个[[prototype]],再把这个实例赋值给了子类的原型,加上constructor属性。就实现了不创造多余属性的目的。

接下来:

function Anm(klass) {
            this.klass = klass;
        }
        Anm.prototype.sayKlass = function () {
            console.log(this.klass);
        };
        function Dog(name, klass) {
            Anm.call(this, klass);
            this.name = name;
        }
        inheriyPrototype(Dog, Anm);
        var dog1 = new Dog('小黄', '犬科动物');
        console.log(dog1);  //Dog {klass: "犬科动物", name: "小黄", constructor: function, sayKlass: function}
        dog1.sayKlass();    //犬科动物
        console.log(Dog.prototype);     //Dog {constructor: function, sayKlass: function}
        console.log(Dog.prototype.isPrototypeOf(dog1));        //true
        console.log(Anm.prototype.isPrototypeOf(dog1));        //true

现在很多程序员普遍认为寄生组合式是最理想的继承范式。在YUI中的一些方法上已经开始在使用了。

javascript中创建对象和实现继承的更多相关文章

  1. 【转】JavaScript中的原型和继承

    请在此暂时忘记之前学到的面向对象的一切知识.这里只需要考虑赛车的情况.是的,就是赛车. 最近我正在观看 24 Hours of Le Mans ,这是法国流行的一项赛事.最快的车被称为 Le Mans ...

  2. 深入理解JavaScript中创建对象模式的演变(原型)

    深入理解JavaScript中创建对象模式的演变(原型) 创建对象的模式多种多样,但是各种模式又有怎样的利弊呢?有没有一种最为完美的模式呢?下面我将就以下几个方面来分析创建对象的几种模式: Objec ...

  3. 谈谈javascript中的prototype与继承

    谈谈javascript中的prototype与继承 今天想谈谈javascript中的prototype. 通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性 ...

  4. javascript中创建对象的方式总结

    javascript中创建对象的方式总结 具体代码如下: //创建对象的方式: //创建方式一 var person=new Object(); person.name='jack'; person. ...

  5. javascript中创建对象的几种不同方法

    javascript中创建对象的几种不同方法 方法一:最直白的方式:字面量模式创建 <script> var person={ name:"小明", age:20, s ...

  6. JavaScript中创建对象的三种方式!

    JavaScript中创建对象的三种方式! 第一种 利用对象字面量! // 创建对象的三种方式! // 1 对象字面量. var obj = { // 对象的属性和方法! name: 'lvhang' ...

  7. javascript中的对象之间继承关系

    相信每个学习过其他语言的同学再去学习JavaScript时就会感觉到诸多的不适应,这真是一个颠覆我们以前的编程思想的一门语言,先不要说它的各种数据类型以及表达式的不同了,最让我们头疼,恐怕就是面向对象 ...

  8. Javascript中的prototype与继承

    通常来说,javascript中的对象就是一个指向prototype的指针和一个自身的属性列表.javascript创建对象时采用了写时复制的理念. 只有构造器才具有prototype属性,原型链继承 ...

  9. 深入 JavaScript 中的对象以及继承原理

    ES6引入了一个很甜的语法糖就是 class, class 可以帮助开发者回归到 Java 时代的面向对象编程而不是 ES5 中被诟病的面向原型编程. 我也在工作的业务代码中大量的使用 class, ...

随机推荐

  1. [luogu4026 SHOI2008]循环的债务 (DP)

    传送门 吐槽洛谷难度标签qwq Solution 显然是一道神奇的DP,由于总钱数不变,我们只需要枚举前两个人的钱数就可知第三个人的钱数 DP的时候先枚举只用前k个币种,然后枚举前两个人的钱数,然后枚 ...

  2. 43.mapping的理解

    主要知识点: mapping的理解     (1)往es里面直接插入数据,es会自动建立索引,同时建立type以及对应的mapping (2)mapping中就自动定义了每个field的数据类型. ( ...

  3. 继续聊WPF——设置网格控件列标题的样式

    我很奇怪的是,微软那厮是怎么搞的,Blend里面居然不能编辑GridView的样式,十万般无奈之下,只好手写XAML来处理了. 要想知道一个控件的样式是如何设置,看控件类的定义很重要,我们来看看Gri ...

  4. Bootstrap 表单控件一(单行输入框input,下拉选择框select ,文本域textarea)

    单行输入框,常见的文本输入框,也就是input的type属性值为text.在Bootstrap中使用input时也必须添加type类型,如果没有指定type类型,将无法得到正确的样式,因为Bootst ...

  5. TCP连接之未连接队列的理解

    tcp服务器在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接. 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认 ...

  6. snmptrap、snmpinform和snmptrapd的详细介绍及其用法

    http://blog.csdn.net/reille/article/details/8712087

  7. DLR概念

    参考文章 动态语言运行时(Dynamic Language Runtime,DLR)是一套基于.NET的类库,它的作用是简化在CLR上开发动态语言的工作,例如DLR中提供了表达式树的创建,代码生成.优 ...

  8. OpenCV学习笔记(六十二)——《OpenCV Computer Version with Python》阅读摘要

    如今python火啊.每次OpenCV自带的ml模块都让我直呼坑爹,索性准备用python来做OpenCV后期的机器学习算法的处理.于是赶紧拿起这本书读读. 适合OpenCV和python都有一定基础 ...

  9. 【传智播客VIP用户专享】Swift教程最新更新

    (1)[传智播客VIP用户专享]Swift教程最新更新 特地贡献出来忘帮顶!!(传智内部学院给的) http://pan.baidu.com/s/1jGmRRIu    提取码:i11g 相关资料下载 ...

  10. PyCharm 运行工程