Object

本文详细解读了JavaScript中Object.defineProperty方法的使用,介绍了如何通过它实现对象属性的动态修改与数据劫持,并展示了Vue项目中利用defineReactive函数实现的数据响应式原理。
摘要由CSDN通过智能技术生成

Object.defineProperty

对一个对象的属性进行修改或者新建
语法:Object.defineProperty(obj, prop, descriptor)
入参说明:对象名称、属性名、属性描述

let object1 = {}
// 已下两种写法相等
Object.defineProperty(object1, "name", {value: "kangkang"}
Object.defineProperty(object1, "name", {
	value: "kangkang",
	configurable: false, // 该属性的描述符是否能够被改变,默认false
	enumerable: false,  // 该属性是否能被遍历到,默认false
	writable: false  // 该属性的值是否能被修改, 默认false
})
// 已下两种写法相等
object1.name = "kangkang"
Object.defineProperty(object1, "name", {
	value: "kangkang",
	configurable: true,
	enumerable: true,
	writable: true
})

以上之外,还有get 和 set 方法
注:描述符分数据描述符和存储描述符;两种描述符无法共存:
数据描述符可选键值:configurable enumerable writable value
存储描述符可选键值: configurable enumerable get set

即:value、writable和get、set无法共存,会报异常

当该对象获取改属性值或者修改该属性值是被调用:

      let obj2 = {}
      obj2.name = "kangkang"
      Object.defineProperty(obj2, "name", {
        enumerable: true,
        configurable: true,
        get () {
          console.log('get')
        },
        set (newname) {
          console.log('set', newname)
        }
      })
      obj2.name // get
      obj2.name = "Mike" // set Mike

vue项目数据劫持功能:
转载:https://www.cnblogs.com/zhangym118/p/8717999.html
关于对象的数据劫持:

export function defineReactive (
  obj: Object,
  key: string,
  val: any,
  customSetter?: Function
) {
  const dep = new Dep()//创建订阅对象
 
  const property = Object.getOwnPropertyDescriptor(obj, key)//获取obj对象的key属性的描述
  //属性的描述特性里面如果configurable为false则属性的任何修改将无效
  if (property && property.configurable === false) {
    return
  }
 
  // cater for pre-defined getter/setters
  const getter = property && property.get
  const setter = property && property.set
 
  let childOb = observe(val)//创建一个观察者对象
  Object.defineProperty(obj, key, {
    enumerable: true,//可枚举
    configurable: true,//可修改
    get: function reactiveGetter () {
      const value = getter ? getter.call(obj) : val//先调用默认的get方法取值
      //这里就劫持了get方法,也是作者一个巧妙设计,在创建watcher实例的时候,通过调用对象的get方法往订阅器dep上添加这个创建的watcher实例
      if (Dep.target) {
        dep.depend()
        if (childOb) {
          childOb.dep.depend()
        }
        if (Array.isArray(value)) {
          dependArray(value)
        }
      }
      return value//返回属性值
    },
    set: function reactiveSetter (newVal) {
      const value = getter ? getter.call(obj) : val//先取旧值
      if (newVal === value) {
        return
      }
      //这个是用来判断生产环境的,可以无视
      if (process.env.NODE_ENV !== 'production' && customSetter) {
        customSetter()
      }
      if (setter) {
        setter.call(obj, newVal)
      } else {
        val = newVal
      }
      childOb = observe(newVal)//继续监听新的属性值
      dep.notify()//这个是真正劫持的目的,要对订阅者发通知了
    }
  })
}

Object.getOwnPropertyDescriptor & Object.getOwnPropertyDescriptors

获取指定对象上一个自有属性对应的属性描述符

const obj = { a: 4 };
const descriptor = Object.getOwnPropertyDescriptor(obj, 'a');
console.log(descriptor.configurable); // true
console.log(descriptor.value); // 42
console.log(descriptor.get); // undefined

const descriptor = Object.getOwnPropertyDescriptors(obj);
console.log(descriptor); // Object { a: Object { value: 4, writable: true, enumerable: true, configurable: true } } 
console.log(descriptor.a); // Object { value: 4, writable: true, enumerable: true, configurable: true }

Object.assign(obj1, obj2)

将obj2中可枚举的属性值转移到obj1中,如果obj1、obj2中有属性的key相同,则obj2中的属性值会进行覆盖。
返回新的obj1
注: 用Object.assign({}, obj) 拷贝对象,如果只有一层,可以作为深拷贝

const obj1= { a: 1, b: 2 };
const obj2= { b: 4, c: 5 };

const objNew= Object.assign(obj1, obj2);

console.log(obj1);
// expected output: Object { a: 1, b: 4, c: 5 }

console.log(objNew);
// expected output: Object { a: 1, b: 4, c: 5 }

Object.keys() & Object.entries() 遍历对象

Object.keys()
Object.entries()返回一个给定对象自身可枚举属性的键值对数组;可用for循环进行遍历获取

const object1 = {
  a: 'somestring',
  b: 42,
  c: 12
};
Object.keys(object1).forEach(item => {
	console.log(item, object1[item]) // "a"  "somestring"
})

Object.entries(object1).forEach(item => {
	console.log(item, item[0]) // ["a", "somestring"]  "a"
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值