zoukankan      html  css  js  c++  java
  • javascript 学习总结(九)面向对象编程

    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");
            
            person1.sayName();   //"Nicholas"
            person2.sayName();   //"Greg"

    工厂模型的方法的缺点是会产生大量重复代码!

    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");
            var person2 = new Person("Greg", 27, "Doctor");
            
            person1.sayName();   //"Nicholas"
            person2.sayName();   //"Greg"
            
            alert(person1 instanceof Object);  //true
            alert(person1 instanceof Person);  //true
            alert(person2 instanceof Object);  //true
            alert(person2 instanceof Person);  //true
            
            alert(person1.constructor == Person);  //true
            alert(person2.constructor == Person);  //true
            
            alert(person1.sayName == person2.sayName);  //false        

    使用new关键字创建对象会经历以下四个过程

    1、创建一个新对象

    2、将构造函数的作用域赋给一个新对象(因此this就指向了这个新对象)

    3、执行构造函数的方法(为这个新对象赋值)

    4、返回新对象

    3、将构造函数当函数用

      function Person(name, age, job){
                this.name = name;
                this.age = age;
                this.job = job;
                this.sayName = function(){
                    alert(this.name);
                };
            }
            
            var person = new Person("Nicholas", 29, "Software Engineer");
            person.sayName();   //"Nicholas"
            
            Person("Greg", 27, "Doctor");  //adds to window
            window.sayName();   //"Greg"
            
            var o = new Object();
            Person.call(o, "Kristen", 25, "Nurse");
            o.sayName();    //"Kristen"

    构造函数当做函数使用就和普通的函数没有任何不同,它属于window对象下面添加的方法而已。由于构造函数创建的对象实际上是创建一个新对象,因此在本质上两者还是不一样的,还是分离的,他们的方法还是不一样的!

    4、将共有的方法方法全局解决不一致的问题

      function Person(name, age, job){
                this.name = name;
                this.age = age;
                this.job = job;
                this.sayName = sayName;
            }
            
            function sayName(){
                alert(this.name);
            }
            
            var person1 = new Person("Nicholas", 29, "Software Engineer");
            var person2 = new Person("Greg", 27, "Doctor");
            
            person1.sayName();   //"Nicholas"
            person2.sayName();   //"Greg"
            
            alert(person1 instanceof Object);  //true
            alert(person1 instanceof Person);  //true
            alert(person2 instanceof Object);  //true
            alert(person2 instanceof Person);  //true
            
            alert(person1.constructor == Person);  //true
            alert(person2.constructor == Person);  //true
            
            alert(person1.sayName == person2.sayName);  //true        

    虽然上面的方法解决了一致的问题,但是定义的全局的方法本身属于window,那么局部和全局就没有分开!所以这个方法使用的并不多见!也不建议使用。

    5、原型模式

    我们创建的任何的一个函数都有一个原型对象,这个属性是一个指针,它指向一个对象,而这个对象的作用是可以有特定的类型的所有的实例共享的方法!

      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();   //"Nicholas"
            
            var person2 = new Person();
            person2.sayName();   //"Nicholas"
          
            alert(person1.sayName == person2.sayName);  //true
            
            alert(Person.prototype.isPrototypeOf(person1));  //true
            alert(Person.prototype.isPrototypeOf(person2));  //true
            
            //only works if Object.getPrototypeOf() is available
            if (Object.getPrototypeOf){
                alert(Object.getPrototypeOf(person1) == Person.prototype);  //true
                alert(Object.getPrototypeOf(person1).name);  //"Nicholas"
            }

    理解原型

    无论什么时候只要是创建了一个函数,就会创建一个原型属性,这个属性指向函数的原型对象。在默认的情况下,原型对象都会包含一个constructor(构造函数属性),这个属性包含一个指向prototype属性所在函数的指针!

    属性读取的顺序

    每当代码读取某个对象的属性时候,都会执行一次搜索,目标是具有给定名字的属性,搜索从对象的实例本身开始查找,如有则返回,没有则继续搜索该对象的原型链,直至搜索到原型链的最外层!

     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();
            var person2 = new Person();
            
            person1.name = "Greg";
            alert(person1.name);   //"Greg" 来自实例
            alert(person2.name);   //"Nicholas" 来自原型

    如果删除了这个元素的实例属性

    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();
            var person2 = new Person();
            
            person1.name = "Greg";
            alert(person1.name);   //"Greg" ?from instance
            alert(person2.name);   //"Nicholas" ?from prototype
            
            delete person1.name;
            alert(person1.name);   //"Nicholas" - from the prototype

    6、hasOwnProperty方法

    这个方法可以检测一个属性是否存在于实例中,还是存在于原型中!hasOwnProperty是从Object继承来的,只要给定属性存在于对象实例中,才会返回true.

     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();
            var person2 = new Person();
            
            alert(person1.hasOwnProperty("name"));  //false
            alert("name" in person1);  //true
            
            person1.name = "Greg";
            alert(person1.name);   //"Greg" ?from instance
            alert(person1.hasOwnProperty("name"));  //true
            alert("name" in person1);  //true
            
            alert(person2.name);   //"Nicholas" ?from prototype
            alert(person2.hasOwnProperty("name"));  //false
            alert("name" in person2);  //true
            
            delete person1.name;
            alert(person1.name);   //"Nicholas" - from the prototype
            alert(person1.hasOwnProperty("name"));  //false
            alert("name" in person1);  //true

    7、Object.keys() 可枚举属性方法

    这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组

     function Person(){
            }
            
            Person.prototype.name = "Nicholas";
            Person.prototype.age = 29;
            Person.prototype.job = "Software Engineer";
            Person.prototype.sayName = function(){
                alert(this.name);
            };
            
            var keys = Object.keys(Person.prototype);
            alert(keys);   //"name,age,job,sayName"

    如果想得到所有实例的属性,无论它是否可以枚举都可以使用这个方法来获取

      function Person(){
            }
            
            Person.prototype.name = "Nicholas";
            Person.prototype.age = 29;
            Person.prototype.job = "Software Engineer";
            Person.prototype.sayName = function(){
                alert(this.name);
            };
            
            var keys = Object.getOwnPropertyNames(Person.prototype);
            alert(keys);   //"constructor,name,age,job,sayName"

    此方法高版本浏览器才支持

    8、简单的原型写法

       function Person(){
            }
            
            Person.prototype = {
                name : "Nicholas",
                age : 29,
                job: "Software Engineer",
                sayName : function () {
                    alert(this.name);
                }
            };
    
            var friend = new Person();
            
            alert(friend instanceof Object);  //true
            alert(friend instanceof Person);  //true
            alert(friend.constructor == Person);  //false
            alert(friend.constructor == Object);  //true

    重写了原型就等于将默认的原型方法覆盖,那么同样的构造方法也会被重写,重写的构造方法指向了Object对象!而不是原来的对象Person

    如果还是想指向之前的构造方法,可以显示的指定

     function Person(){
            }
            
            Person.prototype = {
                constructor : Person,
                name : "Nicholas",
                age : 29,
                job: "Software Engineer",
                sayName : function () {
                    alert(this.name);
                }
            };
    
            var friend = new Person();
            
            alert(friend instanceof Object);  //true
            alert(friend instanceof Person);  //true
            alert(friend.constructor == Person);  //true
            alert(friend.constructor == Object);  //false

    9、原型方法的动态添加

    function Person(){
            }
            
            Person.prototype = {
                constructor: Person,
                name : "Nicholas",
                age : 29,
                job : "Software Engineer",
                sayName : function () {
                    alert(this.name);
                }
            };
            
            var friend = new Person();
            
            Person.prototype.sayHi = function(){
                alert("hi");
            };
            
            friend.sayHi();   //"hi" ?works!

    10、原生对象的原型方法

     alert(typeof Array.prototype.sort);         //"function"
            alert(typeof String.prototype.substring);   //"function"
    
            String.prototype.startsWith = function (text) {//修改原生对象的原型方法
                return this.indexOf(text) == 0;
            };
            
            var msg = "Hello world!";
            alert(msg.startsWith("Hello"));   //true

    11、组合使用构造函数和原型模式创建对象

     
    //构造函数模式
    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); } }; var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1.friends.push("Van"); alert(person1.friends); //"Shelby,Court,Van" alert(person2.friends); //"Shelby,Court" alert(person1.friends === person2.friends); //false alert(person1.sayName === person2.sayName); //true

    12、动态原型模式

                  
            function Person(name, age, job){
            
                //properties
                this.name = name;
                this.age = age;
                this.job = job;
                
                //methods
                if (typeof this.sayName != "function"){
                
                    Person.prototype.sayName = function(){
                        alert(this.name);
                    };
                    
                }
            }
    
            var friend = new Person("Nicholas", 29, "Software Engineer");
            friend.sayName();

    13、寄生构造函数模式

       function Person(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 friend = new Person("Nicholas", 29, "Software Engineer");
            friend.sayName();  //"Nicholas"
     function SpecialArray(){       
     
                //create the array
                var values = new Array();
                
                //add the values
                values.push.apply(values, arguments);
                
                //assign the method
                values.toPipedString = function(){
                    return this.join("|");
                };
                
                //return it
                return values;        
            }
            
            var colors = new SpecialArray("red", "blue", "green");
            alert(colors.toPipedString()); //"red|blue|green"
    
            alert(colors instanceof SpecialArray);

    上诉方法有一点说明下,由于它是依赖外层对象来创建一个新对象,因此不能依赖 instanceof方法来确定属性和方法的来源!它实际上和构造函数的没有关系!

    14、稳妥构造函数模式

       function Person(name, age, job){
                var o = new Object();
                o.sayName = function(){
                    alert(name);
                };    
                return o;
            }
            
            var friend = Person("Nicholas", 29, "Software Engineer");
            friend.sayName();  //"Nicholas"

    此方法不依赖任何new this 关键符!如果要访问对象的方法和属性,只能通过对象已经定义好的方法来获取!

    15、继承

    javascript实现继承是通过原型链来实现的

    function SuperType(){
                this.property = true;//定义一个属性
            }
            
            SuperType.prototype.getSuperValue = function(){//定义的原型方法
                return this.property;
            };
            
            function SubType(){
                this.subproperty = false;
            }
            
            //inherit from SuperType
            SubType.prototype = new SuperType();
            
            SubType.prototype.getSubValue = function (){
                return this.subproperty;
            };
            
            var instance = new SubType();
            alert(instance.getSuperValue());   //true
           
            alert(instance instanceof Object);      //true
            alert(instance instanceof SuperType);   //true
            alert(instance instanceof SubType);     //true
    
            alert(Object.prototype.isPrototypeOf(instance));    //true
            alert(SuperType.prototype.isPrototypeOf(instance)); //true
            alert(SubType.prototype.isPrototypeOf(instance));   //true
    SubType继承SuperType的方法和属性,因此当instance可以直接调用SuperType的方法!
     function SuperType(){
                this.property = true;
            }
            
            SuperType.prototype.getSuperValue = function(){
                return this.property;
            };
            
            function SubType(){
                this.subproperty = false;
            }
            
            //inherit from SuperType
            SubType.prototype = new SuperType();
            
            //new method
            SubType.prototype.getSubValue = function (){
                return this.subproperty;
            };
            
            //override existing method
            SubType.prototype.getSuperValue = function (){
                return false;
            };
            
            var instance = new SubType();
            alert(instance.getSuperValue());   //false

    上面的例子说明,重写的原型会覆盖之前继承的原型,最后返回的往往不是预期的效果

     function SuperType(){
                this.property = true;
            }
            
            SuperType.prototype.getSuperValue = function(){
                return this.property;
            };
            
            function SubType(){
                this.subproperty = false;
            }
            
            //inherit from SuperType
            SubType.prototype = new SuperType();
            
            //使用字面量添加的方法导致上面的方法失效了
            SubType.prototype = {
                getSubValue : function (){
                    return this.subproperty;
                },
            
                someOtherMethod : function (){
                    return false;
                }
            }; 
            
            var instance = new SubType();
            console.log(instance);
            alert(instance.getSuperValue());   //error!

    下面的例子也说明重写原型带来的风险

      function SuperType(){
                this.colors = ["red", "blue", "green"];
            }
    
            function SubType(){            
            }
            
            //inherit from SuperType
            SubType.prototype = new SuperType();
    
            var instance1 = new SubType();
            instance1.colors.push("black");
            alert(instance1.colors);    //"red,blue,green,black"
            
            var instance2 = new SubType();
            alert(instance2.colors);    //"red,blue,green,black"

    原型共享导致两个不同的对象调用的同一个数据

    16、借用构造函数来实现继承

     function SuperType(){
                this.colors = ["red", "blue", "green"];
            }
    
            function SubType(){  
                //inherit from SuperType
                SuperType.call(this);
            }
    
            var instance1 = new SubType();
            instance1.colors.push("black");
            alert(instance1.colors);    //"red,blue,green,black"
            
            var instance2 = new SubType();
            alert(instance2.colors);    //"red,blue,green"

    传递参数

      function SuperType(name){
                this.name = name;
            }
    
            function SubType(){  
                //inherit from SuperType passing in an argument
                SuperType.call(this, "Nicholas");
                
                //instance property
                this.age = 29;
            }
    
            var instance = new SubType();
            alert(instance.name);    //"Nicholas";
            alert(instance.age);     //29

    17、组合继承方式

    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;
            }

    18、原型继承

      function object(o){
                function F(){}
                F.prototype = o;
                return new F();
            }
            
            var person = {
                name: "Nicholas",
                friends: ["Shelby", "Court", "Van"]
            };
            
            var anotherPerson = object(person);
            anotherPerson.name = "Greg";
            anotherPerson.friends.push("Rob");
            
            

    19、寄生组合式继承

      function object(o){
                function F(){}
                F.prototype = o;
                return new F();
            }
        
            function inheritPrototype(subType, superType){
                var prototype = object(superType.prototype);   //create object
                prototype.constructor = subType;               //augment object
                subType.prototype = prototype;                 //assign object
            }
                                    
            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("Nicholas", 29);
            instance1.colors.push("black");
            alert(instance1.colors);  //"red,blue,green,black"
            instance1.sayName();      //"Nicholas";
            instance1.sayAge();       //29
            
           
            var instance2 = new SubType("Greg", 27);
            alert(instance2.colors);  //"red,blue,green"
            instance2.sayName();      //"Greg";
            instance2.sayAge();       //27
  • 相关阅读:
    05数组 字符串数组 多维数组
    android textView的渐入效果
    android颜色表
    ExpandableListView置顶和子list收放
    Adb not responding
    android 一个TextView设置多种颜色
    android 循环操作
    Android异步更新
    android 水波纹
    Android 推门效果
  • 原文地址:https://www.cnblogs.com/shizhouyu/p/4930128.html
Copyright © 2011-2022 走看看