js对象复习20190107

原生js的数据属性,访问器属性

        var foo = {} 
        Object.defineProperty(foo, 'name', {
            configurable: true, 
            enumerable: true,
            writable: true,
            value: 'rose'
        })
        Object.defineProperties(foo, {
            sex: {
                configurable: true, 
                enumerable: true,
                writable: true,
                value: 'man'
            },
            time: {
                configurable: true, 
                enumerable: true,
                writable: true,
                value: 'haha'
            }
        })
        // 在这儿只指定get,则属性不能写入数据,只指定set,属性不能读取数据
        Object.defineProperty(foo, 'age', { // 注意与es6 的proxy作区分
            get: function() {
                return this._age
            },
            set: function(value) {
                this._age = value
            }
        })
        console.log(foo)
        foo.age = 30
        console.log(foo.age, foo)
        // 读取属性的特性
        var descriptor = Object.getOwnPropertyDescriptor(foo, 'name')
        console.log(descriptor)

es6 proxy(注意与上面defineProperty相对比)


        var origin = {
            name: 'rose'
        }
        var handler = {
            get: function(target, key) {
                return target[key]
            },
            set: function(target, key, value) {
                target[key] = value
            }
        }
        var proxy1 = new Proxy(origin, handler)
        proxy1.age = 18
        console.log(origin)

创建对象的方式

 1. 工厂模式(不足:其没有解决对象的识别问题,即不知道究竟是哪个对象


        function creatPersonObject(name, age, sex) {
            var o = new Object()
            o.name = name
            o.age = age
            o.sex = sex
            return o
        }
        console.log(creatPersonObject('rose', 22, 'man'))

2.构造函数模式(不足:在实例化时,如果遇到function都会去实例化function,造成每个实例化后的function不同,没有必要

function Person(name, age, sex) {
       this.name = name
       this.age = age
       this.sex = sex
       this.go = function() {
           console.log('go')
      }
}
        // new 操作符的步骤: 1.创建新的对象,2.将构造函数的作用域赋值给新的对象 3. 执行构造函数 4. 返回新对象
        var person1 = new Person('kobe', 23, 'man')
        var person2 = new Person('durant', 21, 'man')
        console.log(person1, person1 instanceof Person, person1.go == person2.go)

3.原型模式

        function Man(name, age) {
            this.name = name
            this.age = age
        }
        Man.prototype.go = function() {
            console.log('go')
        }
        var man1 = new Man('qw', 12)
        var man2 = new Man('er', 14)
        console.log(man1, man1.go == man2.go)

         3.1 理解原型对象

        /**
         * 构造函数拥有一个prototype属性指向构造函数的原型对象
         * 构造函数的原型对象拥有一个constructor属性指向构造函数,【注】该属性为共享,故实例也拥有constructor属性,且指向构造函数
         * 实例的[[prototype]]指向构造函数的原型对象
         * isPrototypeOf()
         * Object.getPrototypeOf()
         * hasOwnProperty() 判断是属于原型对象的属性,还是属于实例的属性,属于实例的属性,返回true
         * in操作符,单独使用时,不管属性是否为原型属性还是实例属性,若存在,都为true
         * for...in 同上,还要加一个条件:属性的[[Enumerable]]标记为true,可枚举
         * Object.keys() // 返回对象所有支持枚举的属性组成的数组
         * Object.getOwnPropertyNames() // 返回所有属性,不管属性可否枚举
        */
       function People(name) {
           this.name = name
       }
       People.prototype.say = function() {
           console.log('hello')
       }
       var people1 = new People('AA')
       console.log(People.prototype.isPrototypeOf(people1)) // true
       console.log(Object.getPrototypeOf(people1)) // 获取people的原型对象
       console.log(people1.constructor) // People
       console.log(people1.hasOwnProperty('say')) // false
       console.log(people1.hasOwnProperty('name')) // true
       console.log('name' in people1) // true
       console.log('say' in people1) // true
       /*
       如果原型对象以对象字面量的形式书写,则原型对象的constructor属性将不再指向构造函数,因为此时prototype相当于被重写了
       */
      function Foo() {}
      Foo.prototype = {
          name: 'aa',
          age: 18
      }
      console.log(Foo.prototype.constructor) // 此时为Object的构造函数,而非Foo
      var foo = new Foo()
      console.log(foo.constructor) // Object
      // 如果此时constructor的值很重要,则可以将其进行手动修复
      Foo.prototype.constructor = Foo
      console.log(Foo.prototype.constructor) // Foo
      console.log(foo.constructor) // Foo
      // 但是通过上面方式,constructor是可以被枚举出来的,下面的做法可以避免
      Object.defineProperty(Foo.prototype, 'constructor', {
          enumerable: false,
          value: Foo
      })
       // 重写原型可能造成的问题:如果重写发生在实例化之后,则实例的[[prototype]]不会指向重写的原型;一定要是重写!!!
       function Foo2() {}
       var foo2 = new Foo2()
       Foo2.prototype = {
           name: 'dd'
       }
       console.log(foo2.name) // undefined

4.组合使用构造函数与原型模式,上面已经有了

5.动态原型模式(即在构造函数中初始化原型

       function Foo3(name) {
           this.name = name
           if (typeof this.say !== 'function') {
               Foo3.prototype.say = function() {
                   console.log('say!')
               }
           }
       }
       var foo3 = new Foo3('ss')
       console.log(foo3, foo3 instanceof Foo3) // {}, true

6.寄生构造函数模式(有点类似于工厂模式, 不能用instanceof来进行判断,一般不用这个方法)

       function CreateFoo4(name) {
           var o = new Object()
           o.name = name
           o.say = function() {
               console.log(this.name)
           }
           return o
       }
       var foo4 = new CreateFoo4('sd')
       console.log(foo4, foo4 instanceof CreateFoo4) // {}, false

7.稳妥构造函数模式(不使用this和new操作符,其主要作用就是原始传入的数据,不能通过对象直接访问,只能通过函数去获取,保证数据安全,不适合使用instanceof)

       function Foo5(name, age) {
           var o = new Object()
           o.getName = function() {
               return name
           }
           o.getAge = function() {
               return age
           }
           return o
       }
       var foo5 = Foo5('asd', 22)
       console.log(foo5)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值