美文网首页
JavaScript面向对象设计

JavaScript面向对象设计

作者: 郝翔 | 来源:发表于2016-06-09 18:48 被阅读39次

    参考资料:

    疑问

    {object Object}

    创建对象

    1. Object构造函数
    2. 对象字面量

    创建属性

    定义单一属性

    1. 数据属性(默认可以直接创建或者使用Object.defineProperty()
    2. 访问器属性(必须使用Object.defineProperty())

    数据属性

    • 数据属性包含一个数据值的位置,在这个位置进行读取和写入值
    • 数据属性包含多个描述其行为的特性(Configurable,Enumerable,Writable,Vlaue)

    修改属性的默认特性

    • Object.defineProperty()(ECMAScript5)
    • 参数:接受三个参数,属性所在的对象,属性的名字,一个描述符对象,如不指定描述符对象,则除value外都为false
      var person = {};
      Object.defineProperty(person,"name",{
      writable: false,
      value: "haoxiang"
    });
      alert(person.name); // haoxiang
      person.name = "haoqi";
      alert(person.name); // haoxiang
    

    访问器属性

    • 访问器属性不包含数据值,这类属性包含一对函数(getter,setter)
    • 在读取访问器属性时,会调用getter,写入时,会调用setter([[Configurable]],[[Enumerable]],[[get]],[[set]])
    • 访问器的属性不可以直接进行定义,必须使用Object.defineProperty()定义
    var book = {
      _year : 2015,
      edition: 1
    }; // 定义了两个数据属性,其中的`_`用来标记只能通过对象方法访问到的属性
    Object.defineProperty(book,"mouseyear",{
      get: function(){
        return "read";
      },
      set: function(){
        alert("write");
      }
    });
    alert(book.mouseyear);//read,读取属性会调用`get`函数
    book.mouseyear = 200;//write,写入属性会调用`set`函数
    

    来个复杂些的,书上说这个是使用访问器属性的常用方式,主要的特点是设置一个属性的值,会影响其他属性的变化,先提前留个印象

    var book = {
      _year : 2004,
      edition: 1
    }; //定义`book`对象,其中包含`_year`,`edition`数据属性
    Object.defineProperty(book, "year",{
      get :function () {
        return this._year;
      },
      set :function (newValue) {
        if (newValue > 2004) {
          this._year = newValue;
          this.edition += newValue - 2004;
        }
      }
    });
    //接着为`book`对象创建`year`访问器属性,访问器属性是没有`[[Value]]`特性的,它的值就是依靠get,set函数读取和写入
    console.log(book.year);
    //2004,这里我们使用`book.year`读取这个访问器属性,这个访问器属性会使用它的`get`函数,`return this._year`
    book.year = 2005;
    //为对象的访问器属性写入新值,这个值看起来作为了`set`函数的参数,这个传参过程让人有些看不懂,后续我会跟进
    console.log(book._year);
    //2005,由于之前使用了访问器属性的`set`函数,这个函数内部会把`this._year = newValue`,所以这里输出正常,是2005
    alert(book.edition);
    //2,由于之前使用了访问器属性的`set`函数,这个函数内部会把`this.edition += newValue - 2004;,所以这里输出正常,`edition`是2
    

    定义多个属性

    Object.defineProperties()
    参数:接受两个对象参数,第一个对象为要添加或者修改属性的对象,第二个对象为需要在第一个对象中添加的属性

    读取属性的特性

    Object.getOwnPropertyDescriptor()
    参数:接受两个参数,第一参数为属性所在的对象,第二个参数为要读取特性的属性
    返回值:有返回值,返回值为一个对象,包含当前属性的所有特性
    看代码

    var num = {num1 : 1};// 定义一个对象,包含数据属性`num1`
    var res = Object.getOwnPropertyDescriptor(num,"num1");// 使用这个方法,结果是包含属性所有特性的对象,放在res中
    for( d in res){
      console.log(d);
    }
    //value
    //writable
    //enumerable
    //configurable
    //枚举属性的所有特性,也间接说明了如果字面量创造对象,包含的属性为数据属性,访问器属性必须通过方法来创建
    {% endhighlight %}
    
    ### 构造函数模式
    > - 创建已知函数,利用this和函数本身传参的特性
    > - 之后使用new操作符
    > - 通过构造函数模式创造的对象,会有一个`constructor属性`指向构造函数
    
    #### 过程
    ```javascript
      function Person (name,age) {
        this.name = name;
        this.age = age;
      }
      var person1 = new Person("hao","22");
      console.log(person1);
      //Person {name: "hao", age: "22"}
    

    new操作符的大致过程

    1. 创建一个新对象
    2. 将构造函数的作用域给新对象,(因此this就指向新对象)
    3. 执行构造函数内的代码(为新对象添加属性)
    4. 返回新对象

    我大致模拟了这个过程,不一定可以保证必然是正确的,如果大家发现我的想法是错的,可以直接留言

    function Person (name,age,job) {
      this.name = name;
      this.age = age;
      this.job = job;
    }
    var person1 = {}; //创建了一个新对象
    person1.Person = Person;
    console.log(person1.Person);
    //将新对象的一个属性作为变量,将函数的指针(也就是函数名,函数的地址)赋给属性person,因此person1.person指向堆内存中的函数对象
    person1.Person("hao",22,"student");//执行这个函数进行赋值
    console.log(person1);//Object {name: "hao", age: 22, job: "student"}
    

    下面这种的可能性貌似大些:

    function Person (name,age,job) {
      this.name = name;
      this.age = age;
      this.job = job;
    }
    var o = {
    };
    Person.call(o,"hao",22,"student");
    console.log(o);
    //Object {name: "keneth", age: 22, job: "studenet"}
    

    原型模式

    • 函数的prototype属性和原型对象的constructor属性: 函数内部会有prototype属性,这个属性指向保存着所有实例共享的属性和方法的对象,叫做函数的原型对象,在默认情况下,所有的
      原型对象都会获得constructor属性,这个属性包含一个指向prototype属性所在函数的指针。

    相关文章

      网友评论

          本文标题:JavaScript面向对象设计

          本文链接:https://www.haomeiwen.com/subject/hjfsdttx.html