美文网首页
Javascript中理解并创建对象

Javascript中理解并创建对象

作者: 路人丁0417 | 来源:发表于2021-08-30 23:06 被阅读0次

    理解对象

    简单来说,对象是键值对的集合。
    属性类型:数据属性,访问器属性。

    1. 数据属性:Configurable,Enumerable,Writable,Value
      configurable:是否能通过delete删除该属性,对象上定义的属性默认为true.
      enumerable:是否可通过for-in枚举,对象上定义的属性默认为true.
      writable:是否可修改,对象上定义的属性默认为true。
      value:这个属性的值,默认undefined。
      修改属性默认的特性:Object.defineProperty(对象,属性,描述符对象)

      Object.defineProperty(person, 'name', {
        writable: false,
        value: 'Li'
      })
      

      注意:将configurable配置为false之后,不能delete它,也不能修改 它,并且不能将它在改为true了。在调用object.defineProperty()方法,如果不指定configurable、writable、enumerable的值,默认为false。

    2. 访问器属性:getter,setter(非必须)
      configurable: 同数据属性。
      enumerable: 同数据属性。
      get:在读取访问器属性的时候会调用这个函数。
      set:在写入访问器属性的时候会调用这个函数。

          var book = {
            _year:2004,
            edition: 1
          }
          Object.defineProperty(book, "year", {
            get: function() {
              return this._year
            },
            set: function(val) {
              if (val > 2004) {
                this._year = val;
                this.edition += val - 2004
              }
            }
          })
      

      注:_year前面的下划线是一种常用的记号,表示只能通过对象方法访问的属性

      Object.defineProperties(book, 对应属性的描述符对象)
      Object.getOwnPropertyDescriptor(book, "_year"),该方法只能用于实例属性

    创建对象

    创建单个对象: 对象字面量/构造函数
    创建多个对象

    1. 工厂模式

      function createPerson(name, age) {
        var o = new Object();
        o.name = name;
        o.age = age;
        o.sayName = function() {
          alert(this.name)
        }
        return o
      }
      var person1 = createPerson('Li', 23);
      var person2 = createPerson('Di', 13);
      

      优点:可以快速的创建多个相似的对象;
      缺点:无法知道一个对象的类型(对象识别)。

    2. 自定义构造函数

      function Person(name, age) {
        this.name = name;
        this.age = age;
        this.sayName = function() {
          alert(this.name)
        }
      }
      var person1 = new Person('Li', 23);
      var person2 = new Person('Di', 13);
      

      new操作符
      a. 创建一个新对象;
      b. 设置原型链(将新对象的__proto__指向函数的prototype) ;
      c. 将构造函数的作用域赋给新对象(绑定this);
      d. 执行构造函数的代码(为新对象添加属性);
      e. 返回新对象。

      可以用instanceof检测person1和person2的类型
      person1 instanceof Person => true
      person1 instanceof Object => true

      优点:对象类型识别
      缺点:每个对象都有单独的sayName函数实例,这个不必要。

    3. 原型模式

      function Person() {
      }
      Person.prototype.name = 'Li';
      Person.prototype.age = 31;
      Person.prototype.sayName = function() {
        alert(this.name)
      }
      
      var person1 = new Person();
      var person2 = new Person();
      
      

      person1和person2共享所有的属性和方法。

      关于prototype和__proto
      Person.prototype.constructor 指向 Person
      person1.__proto__ 指向 Person.prototype
      Person.prototype.isPrototypeOf(person1) 指向 true
      Object.getPrototypeOf(person1) == Person.prototype
      Object.getPrototypeOf(person1).name 值为:"Li"

      读取对象的某个属性的时候,先在对象实例本身读取,如果没有找到,则去原型对象上去找,如果还没有找到,则沿着原型链继续往上找。
      可以通过person1.hasOwnProperty("age")来检测该属性是否是实例上的属性。
      操作符in: `alert("name" in person1) 不管是实例属性还是原型上的属性都返回true.
      in配合hasOwnProperty()可以检测属性是否是原型属性:

      function hasProtoProperty(object, name) {
        return !object.hasOwnProperty(name) && (name in object)
      }
      

      for-in:返回所有可枚举的属性(enumerable为true),包括实例上的以及原型对象上的。属性没有顺序。如果属性值为undefined或是null会抛出错误或不执行,所以建议先判断。

      Object.keys(person1)获取对象上所有可枚举的实例属性。返回数组。
      Object.getOwnPropertyNames(person1)获取对象上的所有实例属性,不论是否可以枚举。返回数组。

      调用构造函数会为实例添加一个指向最初原型(prototype)的指针(__proto__),如果在调用构造函数之后重新定义prototype,则会切断这个指针,即person.proto不再指向Person.prototype了。

      可以在原生对象(String/Number/Array/……)的原型上添加方法,但是不推荐。

      缺点:所有实例共享属性和方法,属性值不够灵活(当属性值为引用值的时候)

    4. 组合使用自定义构造函数和原型模式
      通过自定义构造函数定义实例属性,原型模式定义共享的属性和方法

      function Person(name, age) {
        this.name = name;
        this.age = age;
      }
      Person.prototype.sayName = function() {
        alert(this.name)
      }
      
      var person1 = new Person("Li", 12);
      var person2 = new Person("Di", 24);
      
    5. 动态原型模式

      function Person(name, age) {
       this.name = name;
       this.age = age;
       // 一下这段代码只在初次调用构造函数的时候执行
       if(typeof this.sayName != "function") {
         Person.prototype.sayName = function() {
           alert(this.name)
         }
       }
      }
      
      var person1 = new Person("Li", 12);
      var person2 = new Person("Di", 24);
      
    6. 寄生构造函数模式
      类似工厂模式,建议在特殊情况下使用。

      function Person(name, age) {
        var o = new Object();
        o.name = name;
        o.age = age;
        o.sayName = function() {
          alert(this.name)
        }
        return o
      }
    
      var person1 = new Person("Li", 12);
      var person2 = new Person("Di", 24);
    
    1. 稳妥构造函数模式
      稳妥对象:没有公共属性,方法也不引用this对象。在安全的环境中使用。

      function Person(name, age){
        var o = new Object();
        o.sayName = function() {
          alert(name)
        }
        return o
      }
      

    相关文章

      网友评论

          本文标题:Javascript中理解并创建对象

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