`
bird12010
  • 浏览: 8088 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

《javascript高级程序设计2》学习笔记6 OOP

阅读更多

 oo是javascript的重点也是难点,这一章我看了好几遍了。个人觉得这章理解起来不是特别容易,所以有些笔记我决定按照自己的理解以及网上一些前辈写的比较好的文章来写,如有不正确望斧正。后续可能会对内容更新。

 

OOP 定义:使用对象时,只关注对象提供的功能,不关注内部细节,更简洁说是,不了解原理的情况下,会使用其功能。

对象  定义:“黑盒子”,不了解内部结构,知道表面的各种操作。

6.1创建对象

var person = new Object();
 person.name = "flyer";
person.age = "26";
person.job = "WED";

person.sayName = function(){
       alert(this.name);
}
person.sayName();

 缺点:使用同一个接口创建很多对象,会产生大量重复的代码。

 

6.1.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("flyer",26,"WED");
        var person2 = createPerson("bird",27,"UE");

        person1.sayName();// flyer
        person2.sayName();// bird

 

优点:抽象了创建具体对象的过程,用函数来封装以特定接口创建对象的细节。

缺点:解决了创建多个相似对象的问题,但没有解决对象识别的问题。

          没有new。

          函数重复,资源浪费。

 

6.1.2 构造函数模式

 

        function Person(name, age, job){ //构造函数以一个大写字母开头
           /* 系统会做的事情:
            * var this = new Object();  声明的this是新的空白对象
            *
            */
            this.name = name;
            this.age = age;
            this.job = job;
            this.sayName = function(){
                alert(this.name);
            }; 
            // 系统会替我们返回   return this   
        }
        
        var person1 = new Person("flyer",26,"WED"); //当在函数加new时,系统会做一些事情
        var person2 = new Person("bird",27,"UE");
        
        person1.sayName();   //"flyer"
        person2.sayName();   //"bird"
             
        alert(person1.constructor == Person);  //true
        alert(person2.constructor == Person);  //true
        /*
         * 对象的constructor属性最初是用来标识对象类型的,检测类型用instanceof操作符更可靠。
         * person1和person2对象既是Object的实例,也是Person的实例。
         */
        alert(person1 instanceof Object);  //true
        alert(person1 instanceof Person);  //true
        alert(person2 instanceof Object);  //true
        alert(person2 instanceof Person);  //true
        
        alert(person1.sayName == person2.sayName);  //false        

 构造函数与其他函数的唯一区别,就是调用方式不同。任何函数,只要通过new操作符来调用,就是构造函数。

 

缺点:每个方法都要在每个实例上重新创建一遍。

在全局作用域中定义的函数实际上只能被某个对象引用,如果对象定义很多方法,那么就要定义很多个全局函数,我们定义的这个引用类型没有封装性可言。

 

6.1.3 原型模式

定义:用原型实例指向创建对象的种类,并且通过拷贝这些原型创建新的对象。


我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法。也就是通过调用构造函数而创建的那个对象的原型对象。使用原型的好处是可以让所有对象实例共享它所包含的属性和方法。换句话说,不必在构造函数中定义对象信息,而是可以将这些信息直接添加到原型对象中。

 

 

function Person(){

}   
Person.prototype.name = "flyer";
Person.prototype.age = 26;
Person.prototype.job = "WED";
Person.prototype.sayName = function(){
    alert(this.name);
};

var person1 = new Person();
person1.sayName(); // "flyer"
var person2 = new Person();
person2.sayName(); // "flyer"

alert(person1.sayName == person2.sayName); // true

 1.理解原型

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性。在默认的情况下,所有prototype属性都会自动获得一个constructor属性,这个属性包含一个指向prototype属性函数的指针。

 

 个人理解原型就是类似于css中的class。

用构造函数加属性

原型加方法

使用hasOwnProperty()方法可以检测一个属性是存在于实例还是原型中。

 

function Person(){

}

Person.prototype.name = "flyer";
Person.prototype.age = 26;
Person.prototype.job = "WED";
Person.prototype.sayName = function(){
    alert(this.name);
};

var person1 = new Person();
var person2 = new Person();

person1.name = "bird";
alert(person1.name); // bird --来自实例
alert(person1.hasOwnProperty("name"));  // true
alert("name" in person1);   //  true

alert(person2.name); // flyer --来自原型
alert(person2.hasOwnProperty("name")); // false
alert("name" in person2); //  true

delete person1.name;
alert(person1.name); // flyer --来自原型
alert(person1.hasOwnProperty("name")); // false
alert("name" in person1); // true
 

 

 

 2.原型与in操作符

无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性。在默认的情况下,所有prototype属性都会自动获得一个constructor属性,这个属性包含一个指向prototype属性函数的指针。

 

 关于原型模式的理解可以参考tom大叔的文章http://www.cnblogs.com/TomXu/archive/2012/04/16/2436460.html

 

3.更简单的原型语法

        function Person(){
        }
        
        Person.prototype = {
            name : "flyer",
            age : 26,
            job: "WED",
            sayName : function () {
                alert(this.name);
            }
        };

        var person = new Person();
        
        alert(person instanceof Object);  //true
        alert(person instanceof Person);  //true
        alert(person.constructor == Person);  //false
        alert(person.constructor == Object);  //true

 

4.原型的动态性

把原型修改为另外一个对象就等于切断了构造函数与最初原型之间的联系。

function Person(){
        }
        var person = new Person();
        Person.prototype = {
            constructor : Person,
            name : "flyer",
            age : 26,
            job: "WED",
            sayName : function () {
                alert(this.name);
            }
        };

        
        person.sayName();  //error

 

 5.原生对象的原型

可以像修改自定义对象的原型一样修改原生的原型。

 

String.prototype.startWith = function(){  //给String添加一个名为startsWith()的方法
      return this.indexOf(text) == 0;
}
var msg = ‘hello world’;

alert(msg.startWith(‘hello’)); // true

 

6.原型对象的问题

 

原型中所有属性是被很多实例共享的,对于包含引用类型的值来说,问题比较突出。

function Person(){
}
 Person.prototype = {
            constructor : Person,
            name : "flyer",
            age : 26,
            job: "WED",
            friends:["bird","stone"],
            sayName : function () {
                alert(this.name);
            }
 };

var person1 = new Person();
var person2 = new Person();

person1.friends.push("andy");

alert(person1.friends);
alert(person2.friends);
alert(person1.friends == person2.friends);

 

 

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

 

    function Person(name,age,job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.friends = ["bing","bird"];
    }

    Person.prototype = {
        constructor : Person,
        sayName : function(){
            alert(this.name);
        }
    }

    var person1 = new Person("flyer",26, "WED");
    var person2 = new Person("tolly",27, "UE");

    person1.friends.push("cally"); 
    alert(person1.friends); // bing bird cally
    alert(person2.friends); // bing bird
    alert(person1.friends === person2.friends); // bing bird
    alert(person1.sayName === person2.sayName); // bing bird
 

6.1.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);
            };
        }
    }

    var person = new Person("flyer", 26, "WED");
    person.sayName();   

 

6.1.6 寄生构造函数模式

在前几种都不适用,可以使用此模式,基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象。

 

6.1.7 稳妥构造函数模式

稳妥对象,指没有公共属性,其方法也不引用this对象。

 

不用this,不用new,适合安全环境。

 

 

6.2继承

许多OO语言都支持:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。由于函数没有签名,在ECMAScript中无法实现接口继承。只支持实现继承。主要靠原型链来实现继承。

 

 

抽象:“抽”--把最主要的特征,跟问题相关的特征抽出来。

封装:看不到里面的东西,用好表面的功能就行了。

继承:从父类上继承出一些方法,属性。

6.2.1 原型链(很少单独使用)

是实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法

 

回顾一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实现,结果会怎么样呢?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系成立。如此层层递进,就构成了实例与原型的链条。

 

        function ParentType(){
            this.property = true;
        }
        ParentType.prototype.getParentValue = function(){
            return this.property;
        };
        // 继承了SuperType
        function SubType(){
            this.subproperty = false;
        }
        SubType.prototype = new ParentType();
        SubType.prototype.getSubValue = function(){
            return this.subproperty;
        };

        var instance = new SubType();
        alert(instance.getParentValue()); // true
        /*
         * 确定原型与实例的2种方法:
         * 1.使用instanceof操作符
         * 2.使用isPrototypeOf()方法
         */
        alert(instance instanceof Object); // true
        alert(instance instanceof ParentType); // true

        alert(ParentType.prototype.isPrototypeOf(instance)); // true
 

 

6.2.2 借用构造函数(很少单独使用)

在子类型的构造函数的内部调用超类型构造函数。用call()或者apply()方法。

 

        function ParentType(){
            this.colors = ["red","green","yellow"];
        }
        
        function SubType(){
            // 继承了SuperType
            ParentType.call(this); 
        }

        var instance1 = new ParentType();

        instance1.colors.push("blue");
        alert(instance1.colors);

        var instance2 = new ParentType();
        alert(instance2.colors);
 

 

6.2.3 组合继承(常用的继承模式)

 

也叫伪经典继承,指的是将原型链和借用构造函数的技术组合在一块,发挥两者之长的一种继承模式。其思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

 

        function ParentType(name){
            this.name = name;
            this.colors = ["red","green","yellow"];

        }

        ParentType.prototype.sayName = function(){
            alert(this.name);
        }
        function SubType(name,age){
            ParentType.call(this,name);
            this.age = age;

        }

        SubType.prototype = new ParentType();

        SubType.prototype.sayAge = function(){
            alert(this.age);
        }

        var instance1 = new SubType("flyer",26);
        instance1.colors.push("blue");
        alert(instance1.colors);
        instance1.sayAge();
        instance1.sayName();

        var instance2 = new SubType("bing",27);
        alert(instance2.colors);
        instance2.sayAge();
        instance2.sayName();

 

 

6.2.4 原型式继承

借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。

        function object(o){
            function F(){}
            F.prototype = o;
            return new F();
        }

        var person = {
            name: "flyer",
            friends: ["Shelby", "Court", "Van"]
        };
        
        var anotherPerson = object(person);
        anotherPerson.name = "Greg";
        anotherPerson.friends.push("Rob");
        
        var yetAnotherPerson = object(person);
        yetAnotherPerson.name = "Linda";
        yetAnotherPerson.friends.push("Barbie");
        
        alert(person.friends);   //"Shelby,Court,Van,Rob,Barbie"

 

6.2.5 寄生式继承

寄生式继承的思路与寄生构造函数和工厂模式类似,即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的做了所有工作一样返回对象。

 

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}

function createAnother(original){
    var clone = object(original); //通过调用函数创建一个新对象
    clone.sayHi = function(){ // 以某种当时来增强这个对象
        alert("hi");
    };
    return clone;   //返回这个对象
}

var person = {
    name:"flyer",
    friends:["bird","stone","bing"]
};

var anotherPerson = createAnother(person);
anotherPerson.sayHi();

 

6.2.6 寄生组合式继承(是引用类型最理性的继承范式)

通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。

 

        function object(o){
            function F(){}
            F.prototype = o;
            return new F();
        }
    
        function inheritPrototype(subType, superType){     //接收两个参数:子类型构造函数和超类型构造函数
            var prototype = object(superType.prototype);   //创建对象  创建超类型原型的一个副本
            prototype.constructor = subType;               //增强对象 为创建的副本添加constructor属性
            subType.prototype = prototype;                 //指定对象 将新创建的对象赋给子类型的原型
        }
                                
        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;
        }

        inheritPrototype(SubType, SuperType);
        
        SubType.prototype.sayAge = function(){
            alert(this.age);
        };
        
        var instance1 = new SubType("flyer", 29);
        instance1.colors.push("black");
        alert(instance1.colors);  //"red,blue,green,black"
        instance1.sayName();      //"flyer";
        instance1.sayAge();       //29
        
       
        var instance2 = new SubType("bing", 27);
        alert(instance2.colors);  //"red,blue,green"
        instance2.sayName();      //"bing";
        instance2.sayAge();       //27

 

分享到:
评论

相关推荐

    韩顺平javascript笔记(最全整理 dom编程 oop 基础语法)

    在韩顺平老师的笔记中,"JS 面向(基于)对象编程.doc"可能详细讲解了JavaScript中的类、构造函数、原型链、继承和封装等面向对象的高级主题;"dom编程.doc"则可能涵盖了常见的DOM操作方法、事件处理和性能优化策略...

    韩顺平编写的java学习笔记(全)

    ### 韩顺平编写的Java学习笔记概览 #### Java平台分类与运行机制 - **J2SE(Java 2 Platform, Standard Edition)**: 标准版Java开发平台,适用于桌面应用程序开发。 - **J2EE(Java 2 Platform, Enterprise ...

    2023年Javascript学习笔记.docx

    2. **剃刀文献(.js文件)**:这里的"剃刀文献"可能是误打,通常我们指的是.js文件,它是JavaScript代码的存储格式,用于在网页中实现动态功能。 3. **HTML与JavaScript的分离原则**:遵循良好的编程实践,JavaScript...

    《javascript设计模式》学习笔记一:Javascript面向对象程序设计对象成员的定义分析

    本篇文章将详细讲解基于《javascript设计模式》的学习笔记,特别是关于对象成员的定义,包括公有成员、公有方法、私有成员以及私有方法。 1. 公有成员 在JavaScript中,对象的所有属性和方法默认都是公有的,这...

    达内学习笔记补充

    【达内学习笔记补充】是一份综合性的IT学习资料,主要涵盖了编程语言的基础以及Web开发的相关技术。这份笔记的目的是为了帮助学习者深入理解和掌握Java和Web开发的关键概念,为那些在达内或其他类似平台上学习的人...

    java学习笔记

    ### Java学习笔记知识点详解 #### Java 平台与开发概述 - **Java平台分类:** - **J2SE(Java SE):** 标准版,适用于桌面应用程序开发。 - **J2EE(Java EE):** 企业版,专为Web应用和服务端应用程序设计。 -...

    达内学习笔记

    【达内学习笔记】是一份综合性的学习资料,包含了丰富的IT知识,主要针对Java编程语言的学习路径。这份笔记集合了达内教育机构的教学精华,旨在帮助学员系统地掌握Java技术,提升开发技能。以下是各部分笔记的主要...

    java学习笔记.zip

    这些"java学习笔记.zip"包含的文件详细涵盖了Java的多个重要方面,包括基础、进阶以及与之相关的框架技术。以下是对每个文件内容的概览: 1. **10、JavaSE:IO流.pdf** Java标准版(JavaSE)中的输入/输出(IO)流...

    flex actionscript学习笔记

    Flex ActionScript 学习笔记是关于使用Adobe Flex技术并结合ActionScript 3.0进行开发的知识总结。ActionScript 3.0是随着Flash CS3一起推出的一种强大的编程语言,相较于之前的ActionScript版本,它有着显著的提升...

    6.JS高级.rar

    "6.JS高级.rar"这个压缩包显然包含了深入学习JavaScript高级特性和实践的笔记和资料,对于想要提升JavaScript技能的前端开发者来说是一份宝贵的资源。 首先,让我们探讨一下JavaScript的基本概念。JavaScript是一种...

    PHP学习笔记总结.doc

    【PHP学习笔记总结】 PHP(超文本预处理器)是一种广泛使用的开源脚本语言,特别适合于Web开发。它能够嵌入HTML中,让开发者在服务器端处理数据,生成动态网页内容。与JavaScript不同,PHP代码在服务器上执行,然后...

    java学习笔记整理(齐全).doc

    ### Java 学习笔记知识点梳理 #### Java 平台概述 - **J2SE(Java 2 Platform Standard Edition)**: 标准版平台,适用于桌面应用程序的开发。 - **J2EE(Java 2 Platform Enterprise Edition)**: 企业版平台,...

    超值个人java学习笔记

    Struts2是基于MVC设计模式的Web应用程序框架,用于简化Java Web开发。它提供了一套处理HTTP请求和响应的机制,以及动作调度、结果渲染、异常处理等功能。 【Hibernate】 Hibernate是一个强大的ORM框架,它自动管理...

    web2笔记留着用

    6. **面向对象编程(OOP)**:许多现代编程语言支持OOP,其中类和对象是核心概念。理解类的定义、对象的实例化以及封装、继承和多态等原则,有助于构建复杂的软件系统。 7. **前端开发**:对于Web2,前端开发涉及...

    javaweb笔记超 详细

    Java Web 是一种基于Java技术的Web应用程序开发领域,它涵盖了从...这些知识点构成了Java Web开发的基础,通过学习和实践,开发者能够创建动态的、数据驱动的Web应用程序,提供丰富的用户体验并与后端数据库进行交互。

    51CTO下载-韩顺平java从入门到精通视频教程(全94讲)学习笔记整理(齐全)

    - **定义与用途**:J2EE 是针对大型企业级应用设计的,支持 Web 应用程序和服务开发。它包含了 J2SE 的所有特性,并额外提供了一些高级服务,如分布式组件模型、Web 服务支持等。 - **特点**:能够处理高负载、高...

    狂神说Java系列笔记.rar

    【狂神说Java系列笔记.rar】是一份涵盖了2020年7月份的全面Java学习资源,其中包含了从基础到高级的多个主题。这个压缩包是针对Java开发者的宝贵资料库,尤其对于初学者和想要深入理解Java技术体系的人而言极具价值...

    PHP学习总结笔记.pdf

    总之,PHP是一种功能强大的Web开发语言,涵盖了从基础语法到高级特性的广泛知识,适用于构建各种类型的Web应用程序。随着技术的发展,PHP的生态系统不断壮大,提供了丰富的工具和框架,方便开发者高效地进行Web开发...

    PHP学习总结笔记资料.pdf

    它的易学性使其成为初学者入门的理想选择,同时也提供了高级特性供专业程序员使用。PHP主要应用于三个方面:服务端脚本、命令行脚本和桌面应用程序开发。 1. **服务端脚本**:PHP与Web服务器和浏览器配合,用于生成...

Global site tag (gtag.js) - Google Analytics