• javaScript 的面向对象程序


    理解对象

       属性类型

        数据属性(数据属性包含一个数据值的位置,这个位置可以读取和写入值,数据属性有4描述)

          [Configurable]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性的特性,或者能否把属性修改为访问器属性,像前面例子中

            那样直接在对象上定义的属性,他们的这个特性默认为true.

           var person = {};
           Object.defineProperty(person,'name',{
              configurable:false,
              value:"Nicholas"
           });
            alert(person.name); // "Nicholas"
           delete person.name;
            alert(person.name); //"Nicholas"

          [Enumerable]: 表示能否通过for-in 循环返回属性。像前面例子中那样直接在对象上定义的属性,它们的这特性默认值为true.

          [Writable]: 表示能否修改属性的值,像前面例子中那样直接子对象上定义的属性,它们的这个属性默认值为true.

           var person = {};
           Object.defineProperty(person,'name',{
              writable:false,
              value:"Nicholas"
           });
           alert(person.name); // "Nicholas"
           person.name = "Greg";
           alert(person.name); //"Nicholas"

          [Value]: 包含这个属性的数值,读取属性值的时候,从这个位置读; 写入属性值的时候把新值保存在这个位置,这个属性的默认值为undefined;

        访问器属性 (访问器属性不能直接定义,必须使用Object.defineProperty() 来定义)

          [Configurable]:表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性的特性,或者能否把属性修改为访问器属性,像前面例子中

            那样直接在对象上定义的属性,他们的这个特性默认为true.

          [Enumerable]: 表示能否通过for-in 循环返回属性。像前面例子中那样直接在对象上定义的属性,它们的这特性默认值为true.

          [Get]: 在读取属性时调用的函数。默认值为undefined。

          [Set]: 在写入属性时调用的函数。默认值为undefined。

            var book={
               _year:2004,
               edition:1
            }
            Object.defineProperty(book,"year",{
              get:function(){
                return this._year;
              },
              set:function(newValue){
                if(newValue > 2004){
                  this._year = newValue;
                  this.edition += newValue -2004;
                }
              }
            })
            book.year = 2005;
            console.log(book.edition) // 2
            var obj = {
                _x:"obj._x",
              _y:"obj._y",
              _z:"Obj._z"
            }
            Object.defineProperty(obj,"x",{ // x属性,只读不写
              get:function(){
                return this._x;
              }
            });
            console.log(obj.x); // "obj._x"
            obj.x = "Rewrite x"; // 尝试修改x属性
            console.log(obj.x); // "obj.x" 写入失败
            
            Object.defineProperty(obj,"y",{ // y属性,只写不能读
              set:function (newValue){
                this._y = newValue;
              }
              
            });
            console.log(obj.y);      // "undefined" 读取失败
            obj.y = "Rewrite obj.y"; // 尝试修改属性
            console.log(obj._y);      // "Rewrite obj.y" 可以写入

            Object.defineProperty(obj,"z",{
              get:function(){
                return this._z;
              },
              set:function (newValue){
                 this._z = newValue;
              }
            });
            console.log(obj.z);     //"obj.z"
            obj.z = "Rewrite obj.z";   // 修改z 属性
            console.log(obj._z);     // "Rewrite obj.z"

         创建访问器属性一般使用两个标准方法:_defineGetter_()和_defineSetter_()。

        var  book = {
                _year;2004,
                edition:1
        };
        // 定义访问器的旧有方法
        book.__defineGetter__("year",function(){
            return this._year;
        });
        book.__defineSetter__("year",function(newValue){
          if(newValue > 2004){
            this._year = newValue;
            this.edition += newValue -2004;
          }
        });
        book.year = 2005;
        console.log(book.edition); // 2

        定义多个属性   对象定义多个属性的可能性很大,利用Object.defineProperties()  方法可以通过描述一次定义多个属性。

        var book = {};
        Object.defineProperties(book,{
          _year:{
            value;2004
          },
          edititon:{
            value;1
          },
          year:{
            get:function(){
              return this._year;
            },
            set:function(newValue){
              if(newValue > 2004{
                this._year = newValue;
                this.edition += newValue -2004;
              }
            }
          }
        })

        读取属性的特性     Object.getOwnPropertyDescriptor() 方法可以取得给定属性的描述符,这个方法接收两个参数  属性所在的对象和要读取其描述的属性

              返回是一个对象: 如果是访问器属性,这个对象属性有   configurable,enumerable,get 和set;

                     如果是数据属性 ,这个的对象的属性有 configurable,enumerable,writable和value。   

              var book = {};
              Object.defineProperties(book,{
                _year:{  
                  value;2004
                },
                edition:{
                  value:1
                },
                year:{
                  get:function(){
                    return this._year;
                  },
                  set:funtion(newValue){
                    if(newValue > 2004){
                      this._year = newValue;
                      this.edition += newValue - 2004;
                    }
                  }
                }
              })

              var descriptor = Object.getOwnPropertyDescriptor(book,"_year");
              console.log(descriptor.value); // 2004
              console.log(descriptor.configurable); //false
              console.log(descriptor.get); // undefined
              var descriptor = Object.getOwnPropertyDescriptor(book,"year");
              console.log(descriptor.value); // undefined
              console.log(descriptor.enumerable) // false
              console.log(typeof descriptor.get) // function

    创建对象

        工厂模式 

        function createPerson(name,age,job){
          var o = new Object();
          o.name = neame;
          o.age = age;
          o.job = job;
          o.sayName = function(){
            console.log(this.name)
          };
          return o;
         }
         var person1 = createPerson("Nicholas",29,"Software Engineer");
         var person2 = createPerson("Greg",27,"Doctor")
          // 函数 createPerson() 能够根据接受的参数来构建一个包含所有必要信息的person对象。

           

       构造函数模式

        function Person(name,age,job){
          this.name = name;
          this.age = age;
          this.job = job;
          this.sayName = function(){
            console.log(this.name);
          }
          var person1 = new Person("Nicholas",29,"Software Enginerer");
          var person 2 = new Person("Greg",27,"Doctor");
         }

            要创建Person 的实例,必须使用new 操作符,以这种方式调构造函数实际上会经历以下4个步骤

              1.创建一个行对象。

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

              3.执行构造函数中的代码(为这个新对象添加属性)

              4.返回新对象。

       原型模式

        function Person(){}
        Person.prototype.name = "Nicholas";
        Person.prototype.age = 29;
        Person.protoype.sayName = function(){
            alert(this.name);
        };
        var person1 = new Person();
        person1.sayName(); // "Nicholas"
        var person2 = new Person();
         person2.sayName();
        alert(person1.sayName == person2.sayName); // true
        

         在实例中无法访问到[[Prototype]],可以通过isPrototypeOf() 方法来确定对象直接是否存在这种关系。

          console.log(Person.prototype.isPrototypeOf(person1)); // true
    
          console.log(Person.prototype.isProtoypeOf(Person2));// true

          Object.getPrototypeOf(),在所有支持的实现中,这个方法返回[[Protoype]]的值。

     console.log(Object.getPrototypeOf(person1) == Person.prototype); // true
    
          console.log(Object.getPrototypeOf(person1).name); // "Nicholas"

         使用delete   操作符则可以完全删除实例属性,可以重新访问原型中的属性。

            function Person(){}
            Person.prototype.name = 'Nicholas';
            Person.prototype.age = 29;
            Person.prototype.job = "Software Engineer";
            Person.protooype.sayName = function(){
              console.log(this.name)
            }
            var person1 = new Person();
            var person2 = new Person();
            person1.name = "Greg";
            console.log(person1.name); // "Greg"    来自实例
            console.log(person2.name); // "Nicholas"   来自原型
            delete person1.name;
            console.log(person1.name); // “Nicholas”  来自原型

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

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

            var p1 = new Person();
            pl.name = "Rob";
            p1.age = 31;
            var p1keys = Object.keys(p1);
            console.log(p1keys); //"name,age"

          无论是否可枚举,都可以使用Object.getOwnPropertyNames();

            var keys = Object.getOwnPertyNames(Person.protoype);
           console.log(keys) // “constructor,name,age,job,sayName”

           对象字面量来重写原型

            function(){}
            Person.prototype = {
              name:"Nicholas",
              age:29,
              job:"Software Engineer",
              sayName:function(){
                console.log(this.name);
              }
            }

          重设构造函数  

          Object.defineProperty(Person.prototype."constructor",{
            enumerable:false,
            value:Person
          })

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

           function Person(){}
           var friend = new Person();
           Person.prototype = {
              constructor:Person,
              name:"Nicholas",
              age:29,
              job:"Software",
              sayName:function(){
                console.log(this.name)
              }
           };
           friend.sayName(); // error

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

           function Person(name,age,job){
              this.name = name;
              this.age = age;
              this.job = job;
              this.friends = ["Shelby","Court"];
           }
          Person.protoype = {
            constructor :Person,
            sayName:function(){
              console.log(this.name)
            }
          }
          var person1 = new Person("Nicholas",29,"Software Engineer");
          var person2 = new Person("Greg",27,"Doctor")

          person1.friends.push("Van");
          console.log(person1.friends); // "Shelby,Count,Van"
          console.log(person2.friends); //"Shelby,Count"
          console.log(person1.friends === person2.frends); // false
          console.log(person1.sayName === person2.sayName); // true

       动态原型模式

          funciton Person(name,age,job){
            // 属性
            this.name = name;
            this.age = age;
            this.job = job;
            // 方法
            if(typeof this.sayName != "function"){
              Person.prototype.sayName = function(){
                console.log(this.name)
              }
            }
          }
          var friend = new Person("Nicholas",29,"Softeare Engineer");
          friend.sayName();

       寄生构造函数模式

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

         稳妥构造函数模式

        function Person(name,age,job){
          // 创建要返回的对象
          var o = new Object();
          // 可以在这里定义私有变量和函数
          // 添加方法
          o.sayName = function(){
            console.log(name)
          }
          // 返回对象
          return o;
        }
        var friend = Person("Nicholas",29,"Software Engineer");
        friend.sayName(); // "Nicholas"

    继承  (ECMAScript 只支持实现继承,而且实现继承主要依靠)

      原型链

        function SuperType(){
          this.property = true;
        }
        SuperType.protoype.getSuperValue = function(){
          return this.property;
        };
        function SubType(){
          this.subproperty = false;
        }
        // 继承了 SuperType
        SubType.prototype = new SuperType();
        SubType.prototype.getSubValue = function(){
            return this.subproperty;
        };
        var instance = new SubType();
        console.log(instance.getSuperValue()) // true
        // 在调用 instance.getSuperValue() 会经历三个搜索步骤1.搜索实例2.搜索SubType.prototype;3.搜索SuperType.ptototype ,最后一步才会找到方法

          1.所有函数的默认原型都是Object的实例,默认原型会包含一个内部指针,指向 Object.prototype  这也是所有自定义类型都会继承 toString() ,valueOf() 等默认方法的根本原因。

          2.确定原型和实例的关系 (第一种方式是使用instanceof,  第二个方式是使用isPrototypeOf())

            console.log(instance instanceof Object);  // true
            console.log(instance instanceof SuperType) // true
            console.log(instance instanceof SuperType) //true
          
             console.log(Object.prototype.isPrototypeOf(instance)); // true
            console.log(Object.prototype.isPrototypeOf(instance)); // true
    console.log(Object.prototype.isPrototypeOf(instance)); // true

          3.有时候需要重新超类中的某个方法,给原型添加方法一定要房子替换原型语句之后。

            function SuperType(){
              this.property = true;
            }
            SuperType.prototype.getSuperValue = function(){
              return this.property;
            }
            function SubType(){
              this.subproerty = false;
            }
            // 继承了SuperType
            SubType.prototype = new SuperType();
            // 添加新方法
            SubType.prototype.getSubValue = function(){
              return this.subproperty;
            };
            // 重写超类型中的方法,
            SubType.prototype.getSuperValue = function(){
              return false;
            }
            var instance = new SubType();
            console.log(instance.getSuperValue()); // false

           4.原型链的问题 

           function SuPerType(){
                  this.colors = ['red','blue',"green"]
           }
           function SubType(){}
           // 继承了 SuperType
           var instance1 = new SuperType();
          instancel.colors.push("black");
          console.log(instance1.colors);
          
          var instance2 = new SubType();
          console.log(instance2.colors); //"red,blue,green,black"
          var instance2 = new SubType();
          console.log(instance2.colors); // "red,blue,green,black"

      借用构造函数 (函数只不过是在特定环境中执行代码的对象,因此通过使用apply() 和 call() 方法也可以在将来新创建的对象上执行构造函数)

        function SuperType(){
          this.colors = ["red","blue","grren"];
        }  
        function SubType(){
          // 继承了SuperType
          SuperType.call(this);
        }
       var instance1 = new SubType();
       instance1.colors.push("black");
       conole.log(insstance1.colors); // 'red,blue,green,black'
       var instance2 = new SubType();
       console.log(instance2.colors); //"red,blue,green"
       

      组合继承(是将原型链和借用构造函数组合到一起)

        function SuperType(name){
               this.name = name;
            this.colors = ["red","blue","green"]
        }
        SuperType.prototype.sayName = function(){
          console.log(this.name);
        }
       function SubType(name,age){
          // 继承属性
          SuperType.call(this,name);
    this.age = age;
       }
        //继承方法
       SubType.prototype = new SuperType();
       SubType.prototype.sayAge = function(){
         console.log(this.age);
       }
        var instancel = new SubType("Nicolas",29);
        instancel.colors.push("black")
        console.log(instancel.colors); // "red,blue,green,black"
        instancel.sayName(); // "Nicholas" 
        instancel.sayAge();         //29
        
       var instnce2 = new SubType("Greg",27);
       console.log(instnce2.colors); // "red,blue,green"
       instance2.sayName();      // "Greg"
       instance2.sayAge();      // 27

      原型式继承

        var person = {
          name:"Nicholas",
          friends:["Shelby","Court","Van"]
        }
        var anotherPerson = Object.create(person);
        anotherPerson.name = "Greg";
        anotherPerson.friends.push("Rob");

        var yetAnotherPerson = Object.create(person);
        yetAnotherPerson.name = "Linda";
        yetAnotherPerson.friends.push("Barbie");
        
        console.log(person.friends); // "Shelby,Court,Van,Rob,Barbie"
        var person = {
          name:"Nicholas",
          friends:["Shelby","Court","Van"]
        }
        var anotherPerson = Object.create(person,{
            name:{
              value:"Greg"
            }
        })
        console.log(anotherPerson.name); // "Greg"

      寄生式继承

      function createAnother(original){
          var clone = Object(original);   // 通过调用函数创建一个新对象
          clone.sayHi = function(){ // 以某种方式来增强增对象
            console.log("hi")
          }
          return clone;    // 返回这个对象   }
      var person = {
        name:"Nicholas",
        friends:["Shelby","Court","Van"]
      };
      var anotherPerson = createAnother(person);
      anotherPerson.sayHi(); // "hi"

      寄生组合式继承

      function SuperType(name){
        this.name = name;
        this.colors = ["red","blue","green"];
      }
      SuperType.prototypes.sayName = function(){
        SuperType.call(this,name); // 第二次调用SuperType
        this.age = age;
      }
      SubType.prototype = new SuperType(); // 第一次调用 SuperType
      SubType.prototype.constructor = SubType;
      subType.prototype.sayAge = function(){
        console.log(this.age)
      }
  • 相关阅读:
    Hbase学习02-API操作
    Hbase学习01-shell操作
    09 | 普通索引和唯一索引,应该怎么选择?
    08 | 事务到底是隔离的还是不隔离的?
    07 | 行锁功过:怎么减少行锁对性能的影响?
    06 | 全局锁和表锁 :给表加个字段怎么有这么多阻碍?
    05 | 深入浅出索引(下)
    04 | 深入浅出索引(上)
    03 | 事务隔离:为什么你改了我还看不见?
    02 | 日志系统:一条SQL更新语句是如何执行的?
  • 原文地址:https://www.cnblogs.com/nmxs/p/11993658.html
Copyright © 2020-2023  润新知