重点来了,我认为这一章值得好好地反复地看。看第一遍 还是懵懵懂懂,现在看第二遍,终于能看出点意思了。

创建对象

  1. 工厂模式

    function createPerson(name, age, job){
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function(){
    alert(this.name);
    };
    return o;
    } var person1 = createPerson("Nicholas", 29, "Software Engineer");
    var person2 = createPerson("Greg", 27, "Doctor");

    优点:解决了Object构造函数或对象字面量创建多个对象代码重复的问题

    缺点:无法识别对象.

  2. 构造函数模式:
    function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
    alert(this.name);
    };
    }
    var person1 = new Person("Nicholas", 29, "Software Engineer");
    alert(person1.constructor == Person);
    alert(person1 instanceof Object);
    alert(person1 instanceof Person);

    优点:可以将它的实例识别为一种特定的对象

    缺点:每个方法都要在每个实例上重新创建一遍,增加不必要的内存开支

  3. 原型模式
    function Person(){
    }
    Person.prototype.name = "Nicholas";
    Person.prototype.age = 29;
    Person.prototype.job = "Software Engineer";
    Person.prototype.sayName = function(){
    alert(this.name);
    };
    var person1 = new Person();
    person1.sayName(); var person2 = new Person();
    person2.sayName();
    alert(person1.sayName === person2.sayName);

    原型模式创建的属性对象是由所有实例共享的。

    缺点:原型模式在包含引用类型时,实例共享会引起比较严重的问题。

    在所有实现中都无法直接访问到prototype,只通通过isPrototypeOf()来检验对象之间是否存在这种关系。例:Person.prototype.isPrototypeOf(person1)

    在实例中添加一个与原型中的同名属性,会在实例中创建该属性,而不会改变原型的值

    var person1 = new Person();
    var person2 = new Person();
    person1.name = "Greg";
    alert(person1.name); //"Greg"——来自实例
    alert(person2.name); //"Nicholas"——来自原型

    hasOwnProperty()检测一个属性是否在实例中;in 检测是否能访问到访属性,可能是在实例中,也可能是在原型中;

    /*检测属性是否存在于原型中*/
    function hasPrototypeProperty(object, name){
    return !object.hasOwnProperty(name) && (name in object);
    }

    更简单的原型:

    function Person(){
    }
    Person.prototype = {
    constructor : Person,
    /*用字面量定义prototype时,要设置它的constructor,不然它的constructor会指向Object*/
    name : "Nicholas",
    age : 29,
    job : "Software Engineer",
    sayName : function (){
    alert(this.name);
    }
    };
    /*这样设置有一点不足,会使constructor变为可枚举的,如果是支持ECMAScript5的浏览器,可用Object.defineProperty()是方法来设置constructor*/
    /*Object.defineProperty(Person.prototype, "constructor",{
    enumerable:false,
    value:Person
    });*/

    实例中的指针仅指向原型,而不指向构造函数

  4. 组合使用构造函数模式和原型模式

    构造函数模式用于定义实例属性,原型模式用于定义方法和共享属性。

    function Person(name,age,job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Shelby","Court"];
    } Person.prototype = {
    constructor : Person,
    sayName : function(){
    alert(this.name);
    }
    }
  5. 动态原型模式

    把所有信息封装到构造函数中,在构造函数中初始化原型。

    优点:解决了独立的构造函数模式和原型模式独立的问题,又同时保持了两者的优点。

    使用这种方法创建对象,不能用对象字面量重字原型。

    function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    //方法
    if(typeof this.sayName != "function"){
    Person.prototype.sayName = function(){
    alert(this.name);
    };
    }
    }
  6. 寄生构造函数模式

    除了用new操作符并把使用的包装函数叫做构造函数外,这个方法与工厂模式是一样的

    例:具有额外方法的特殊数组,不又直接修改Array的构造函数

    function SpecialArray(){
    //创建数组
    var values = new Array(); //添加值
    values.push.apply(values, arguments); //添加方法
    values.toPipedString = function(){
    return this.join("|");
    }; return values;
    }
    var colors = new SpecialArray("red","blue","green");
    alert(colors.toPipedString());

    使用这种模式,建议不要与其他模式混用

继承

  1. 通常说的继承有接口继承和实现继承,由于js无方法签名,所以不支持接口继承。只通过原型链实现了实现继承。
  2. 原型链

    实现方法:SubType.prototype = new SuperType();

    注1:子类型需要重写超类方法或添加超类中不存在的方法,需要在实现继承语句之后,这样才能屏蔽超类方法

    注2:在通过原型链实现继承时,不能使用对象字面量方法创建原型方法,因为这样做会重写原型链

  3. 借用构造函数(伪造对象/经典继承)

    在子类型构造函数的内部调用超类型构造函数SuperType.call(this);

    比原型链继承的优点是,解决了实例共享的问题,并可以传递参数

    缺点同实例相同,也具有方法不能共享的问题

  4. 组合模式
    function SuperType(name){
    this.name = name;
    this.colors = ["red","blue","green"];
    }
    SuperType.prototype.sayName = function(){
    alert(this.name);
    }; function SubType(name, age){
    SuperType.call(this,name); this.age = age;
    } SubType.prototype = new SuperType(); SubType.prototype.sayAge = function(){
    alert(this.age);
    }; var instance1 = new SubType("Nicholas",29);
    instance1.colors.push("black");
    alert(instance1.colors);
    instance1.sayName();
    instance1.sayAge(); var instance2 = new SubType("Greg",27);
    alert(instance2.colors);
    instance2.sayName();
    instance2.sayAge();
  5. 原型式继承
    function object(o){
    function F(){}
    F.prototype = o;
    return new F();
    }

    实现对传入对象o的浅复制,IE9+的Object.create(o)有相似功能

精读《javascript高级程序设计》笔记三——面向对象的程序设计的更多相关文章

  1. javascript高级编程笔记05(面向对象)

    面向对象设计 es中有两种属性:数据属性和访问器属性 数据属性: 数据属性包含一个数据值的位置,在这个位置可以读取和写入值,数据属性有4个描述其行为的特性 [[Configurable]]:表示能否通 ...

  2. Javascript基础回顾 之(三) 面向对象

    本来是要继续由浅入深表达式系列最后一篇的,但是最近团队突然就忙起来了,从来没有过的忙!不过喜欢表达式的朋友请放心,已经在写了:) 在工作当中发现大家对Javascript的一些基本原理普遍存在这里或者 ...

  3. javascript高级编程笔记01(基本概念)

    1.在html中使用JavaScript 1.  <script> 元素 <script>定义了下列6个属性: async:可选,异步下载外部脚本文件. charset:可选, ...

  4. 《JavaScript高级程序设计》笔记:面向对象的程序设计(六)

    面向对象的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象. 理解对象 创建自定义对象的最简单的方法就是创建一个Object的实例,然后再为它添加属性和方法.例 ...

  5. JavaScript高级程序设计笔记之面向对象

    说起面向对象,大部分程序员首先会想到 类 .通过类可以创建许多具有共同属性以及方法的实例或者说对象.但是JavaScript并没有类的概念,而且在JavaScript中几乎一切皆对象,问题来了,Jav ...

  6. javascript 高级程序设计学习笔记(面向对象的程序设计) 1

    Object构造函数或对象字面量都可以用来创建对象,但这些方式有个明显的缺点:使用相同一个接口创建很多对象,会产生大量重复代码. 工厂模式 //工厂模式 function createDog (nam ...

  7. javascript 高级程序设计学习笔记(面向对象的程序设计)继承

    ECMAScript中描述了原型链的概念,原型链是实现继承的主要方法. 实现原型链继承有一种基本模式 function SuperType () { this.property = true; } S ...

  8. javascript 高级程序设计学习笔记(面向对象的程序设计) 2

    在调用构造函数时会为实例添加一个指向最初原型的指针,我们可以随时为原型添加属性和方法,并且能在实例中体现出来,但如果是重新了原型对象,那就会切断构造函数与最初原型的联系. function Dog ( ...

  9. 《JAVASCRIPT 高级程序设计》读书笔记六 面向对象的程序设计

    一   对象属性 a.对象定义: 无序属性的集合,其属性可以包含基本值.对象或者函数: b.两种创建方式: 1.构造函数: var person = new Object(); person.name ...

随机推荐

  1. chrome调试工具常用功能整理(转)

    Elements chrome devtools 中 Elements panel 是审查 dom 元素和 css 的, 可以实时修改 dom/css. windows: ctrl + shift + ...

  2. struts 2 debug标签隐藏不显示

    struts2 的标签debug在页面中应用,并且struts的配置文件中也设置为开发模式,但是这个标签却被隐藏了,究其原因,是因为页面中body元素生命了class,其样式覆盖了原来的样式. 比如: ...

  3. random background

    function roll(){ var bg = document.getElementById("loginbg"); var rnd = Math.floor(Math.ra ...

  4. "Classifying plankton with deep neural networks" notes

    cross entropy loss is not quite the same as optimizing classification accuracy. Althougth the two ar ...

  5. Python之路第五天,基础(5)-序列化和字符串格式化

    序列化 Python中用于序列化的两个模块 json 用于『字符串』和『python基本数据类型』间进行转换 pickle 用于『python特有的类型』和『python基本数据类型』间进行转换 js ...

  6. Dialog 顶部黑线问题

    Dialog 顶部黑线问题 样式如下: [java] view plaincopyprint? <style name="Transparent_Dialog"> &l ...

  7. Linux进程间通信——使用消息队列

    下面来说说如何用不用消息队列来进行进程间的通信,消息队列与命名管道有很多相似之处.有关命名管道的更多内容可以参阅我的另一篇文章:Linux进程间通信——使用命名管道   一.什么是消息队列 消息队列提 ...

  8. $(window).width() is not a function

    昨天在帮同事调试JS的时候,FF报错了,$(window).width() is not a function.我以前也是这么用的,都没问题,为什么现在就报错了呢? 这是因为jQuery用" ...

  9. 使用Vitamio打造自己的Android万能播放器(4)——本地播放(快捷搜索、数据存储)

    前言 关键字:Vitamio.VPlayer.Android播放器.Android影音.Android开源播放器 本章节把Android万能播放器本地播放的主要功能(缓存播放列表和A-Z快速查询功能) ...

  10. [置顶] android利用jni调用第三方库——第三篇——编写库android程序整合第三方库libhello.so到自己的库libhelloword.so

    0:前言: 在第二篇中,我们主要介绍了丙方android公司利用乙方C++公司给的动态库,直接调用库中的方法,但是这样方式受限于: 乙方C++公司开发的动态库是否符合jni的规范,如果不规范,则不能直 ...