理解对象

  属性类型

    数据属性(数据属性包含一个数据值的位置,这个位置可以读取和写入值,数据属性有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)
  }

javaScript 的面向对象程序的更多相关文章

  1. JavaScript的面向对象编程(OOP)(一)——类

    在学习JavaScript面向对象的编程之前,需要知道,并了解面向对象的一些基本的常识.初学者中大多数都以为面向对象中,面向对象的编程是很重要和占据很大一部分精力.笔者在之前也是认为OOP是面向对象的 ...

  2. javascript进阶——面向对象特性

    面向对象的javascript是这门语言被设计出来时就考虑的问题,熟悉OOP编程的概念后,学习不同的语言都会发现不同语言的实现是不同的,javascript的面向对象特性与其他具有面向对象特性的语言的 ...

  3. javascript 的面向对象特性参考

    最近在看用javascript+css实现rich client.javascript 也是一个蛮有意思的语言.特别是其面向对象的实现和其他“标准”的OO launguage有很大的不同.但是,都是动 ...

  4. JavaScript中国象棋程序(0) - 前言

    “JavaScript中国象棋程序” 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.希望通过这个系列,我们对博弈程序的算法有一定的了解.同时,我们也将构建出一个不错的中国象棋程序 ...

  5. JavaScript中国象棋程序(1) - 界面设计

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第1节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  6. JavaScript中国象棋程序(2) - 校验棋子走法

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第2节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  7. JavaScript中国象棋程序(3) - 电脑自动走棋

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第3节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  8. JavaScript中国象棋程序(4) - 极大极小搜索算法

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第4节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  9. JavaScript中国象棋程序(5) - Alpha-Beta搜索

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第5节. 这一系列共有9个部分: 0.JavaScript中国象 ...

  10. JavaScript中国象棋程序(6) - 克服水平线效应、检查重复局面

    "JavaScript中国象棋程序" 这一系列教程将带你从头使用JavaScript编写一个中国象棋程序.这是教程的第6节. 这一系列共有9个部分: 0.JavaScript中国象 ...

随机推荐

  1. 出海浪头之上,共探CDN进化新支力

    CDN技术自问世以来已超过20个年头,在云计算与AI深度融合的大趋势下,各行业实际业务需求已发生巨变,下一代CDN技术又将走向何方?8月16日,"抓住泛娱热趋,打通增长脉络--大浪淘沙之后的 ...

  2. 5个必知的高级SQL函数

    5个必知的高级SQL函数 SQL是关系数据库管理的标准语言,用于与数据库通信.它广泛用于存储.检索和操作数据库中存储的数据.SQL不区分大小写.用户可以访问存储在关系数据库管理系统中的数据.SQL允许 ...

  3. C#|.net core 基础 - 如何判断连续子序列

    前两天同事遇到了一个小需求,想判断一个集合是不是在另一个集合中存在,并且要求顺序一致,然后一起讨论了下应该怎么做,有没有什么比较好的方式?下面分享一下我们想到的方法,如果你也有不同的想法也可以分享给我 ...

  4. HTML – Native Dialog Modal

    前言 之前介绍 Native Form 的时候有提及过 method="dialog", 但由于它太新了, 所以没去研究. 这篇就介绍一下. Dialog 也好 Modal 也好, ...

  5. Go runtime 调度器精讲(十):异步抢占

    原创文章,欢迎转载,转载请注明出处,谢谢. 0. 前言 前面介绍了运行时间过长和系统调用引起的抢占,它们都属于协作式抢占.本讲会介绍基于信号的真抢占式调度. 在介绍真抢占式调度之前看下 Go 的两种抢 ...

  6. Android Qcom USB Driver学习(十三)

    DPM Device Policy Manager deals with the USB Power Delivery resources used by one or more ports on t ...

  7. USB协议详解第6讲(USB描述符-端点描述符)

    1.USB描述符 USB描述符有设备描述符.标准配置描述符.接口描述符.端点描述符.字符串描述符,HID设备有HID描述符.报告描述符和物理描述符.今天主要是学习USB端点描述符的组成. 2.端点描述 ...

  8. mysql外联数据库

  9. SaaS架构:开放平台架构设计

    大家好,我是汤师爷~ 今天聊聊开放平台架构设计. 为什么需要搭建开放平台 增强产品能力 开放平台能够让三方开发者和合作伙伴开发新的应用或服务,增加原有SaaS产品能力.这样就可以满足更多用户需求,从而 ...

  10. kubernetes拉取私有镜像仓库的镜像

    kubernetes拉取私有镜像仓库时需要使用镜像仓库的账号密码 方式: apiVersion: v1 kind: Pod metadata: name: private-reg spec: cont ...