JavaScript对象

属性描述符

只针对name这个属性,假如对象有其他属性的话则不受影响,如果调用Object.defineProperty()时,如果这三个参数都不指定,那么全部默认为false

let obj = {}
Object.defineProperty(obj, 'name', {
  configurable: false,  //是否可以配置属性描述符
  writable: false,  //是否可以改写属性的值
  enumerable: false,  //控制属性是否会出现在对象的枚举当中(遍历的到不)
  value: '属性标识符'  //属性的值
})

不变性

有时候需要创建一个变量是不变的,不只是对于简单值,引用值里面的值也不变。也就是说可以用属性描述符,即configurable:falsewritable:false去创建一个真正的常量属性。

      Object.defineProperty(person, "age", {
        configurable: false,
        writable: false,
        value:2,
      });

禁止扩展

如何禁止一个对象再添加新的属性,可以使用Object.preventExtensions(obj)

密封

假如想一个对象即不能添加新属性也不能改变既有属性的值,可以一个一个的给对象属性添加属性描述符,也可以使用Object.seal(obj)去创建一个密封对象,它会自动完成上面的功能。

冻结

Object.freeze(obj)会创建一个冻结对象,这个方法实际上会调用seal。
如果在项目进行优化的时候,有一个数组或者object,并且确信数据不会修改,可以使用冻结让性能大幅提升

JavaScript的getter和setter

【GET】

get,获取的意思,平常对于对象中数据的获取大部分是直接调用,如下

let a = {}
a.name = '9527'
console.log(a.name); //9527

但是在使用.的时侯默认调用了对象的内置get函数去获取对象的值,获取的路径是先在对象中查找是否具有同名的属性,没有的话就会去原型链上查找,如果一直没有则返回undefined


let a = {}

a.__proto__.age = 21

console.log(a.age); //21

console.log(a.name); //undefined

但是当自己在对象中声明了get函数后并且没有声明set函数,则不能再对对象的属性进行修改

let a = {
	name: 'sifan',
	get name() {
		return this.name
	},
}
console.log(a.name) //undefined
a.name = 'sifan111'
console.logo(a.name) //undefined

所以当设置了get或set函数后,js就不在关心value和writable属性,而是去监听get、set函数还有configurable与enumerable属性

【Getter】

当我们获取一个对象的属性的时候,就会调用getter函数,但首先要给对象设置getter,否则返回undefined,当给对象定义了getter和setter后,js也会忽略value和writable,而且优先级比get高

    let a = {
      get name() {
        console.log('调用了自己的方法get');
        return this._name
      },
      set name(val) {
        console.log('调用自己的方法set');
        this._name = val
      }
    }
	Object.defineProperty(a,'name',{
      get: function() {
        console.log('调用getter函数');
        return this._name + 'getter'
      }
	 })
	 console.log(a.name) //undefinedgetter
	 a.name = '11
	 console.log(a.name) //11getter

【setter】

当需要修改一个属性的值的时候,会触发set函数,并且传入一个参数val就是想要赋予的值

【vue】

在Vue2中,Object.defineProperty是vue的响应式和双向绑定的主要实现底层,在set中监听属性的改变,并调用notify()函数去通知使用到这个函数的节点的值更新为最新的值,如下部分代码:

 Object.defineProperty(data, key, {
            enumerable: true,
            configurable: true,
            get() {
              if (Dep.target) {
                dep.addSub(Dep.target);
              }
              return val;
            },
            set(newValue) {
              if (val === newValue) {
                return;
              }
              // 数据发生变化 dep通知wather更新
              val = newValue;
              dep.notify();
            },
   });

undefined类型的值和找不到值返回的undefined的区别

可以判断这个属性是否存在对象或者原型链上

使用in操作符

in操作符可以检查属性是否存在于对象及其对象的原型链之中

      const obj = {
        a: undefined,
      };
      obj.__proto__.c=undefined
      console.log(obj.a);//undefined
      console.log(obj.b);//undefined

      console.log("a" in obj);//true
      console.log("b" in obj);//false
      console.log("c" in obj);//true

但是in操作符不能判断一个值是否在数组中,因为in操作符检测的式容器内的某个属性名,对于数组来说包含的属性名是下标

let arr = ['a', 'b', 'c']

console.log('a' in arr); //false

console.log(1 in arr); //true
使用hasOwnProperty()

in操作符不同的是,hasOwnProperty()是不会检测原型链,也就是只查找自己本身的属性,而且也是检测属性名

      const obj = {
        a: undefined,
      };
      obj.__proto__.c=5
      console.log(obj.hasOwnProperty("a"));//true
      console.log(obj.hasOwnProperty("b"));//false
      console.log(obj.hasOwnProperty("c"));//false
	let arr = ['a', 'b', 'c']

	console.log(arr.hasOwnProperty('a')); //false
 
	console.log(arr.hasOwnProperty(1)); //true

遍历

for...in可以遍历对象属性列表,注意:即可以遍历数组,也可以遍历对象

const array = [1, 2, 3, 4];
for (let i in array) {
  console.log(i, array[i]);
}
// 0 1
// 1 2
// 2 3
// 3 4

for...of可以遍历数组值列表,注意:只能遍历数组,不能遍历对象

const array = [1, 2, 3, 4];
for (let index of array) {
  console.log(index);
}
// 1
// 2
// 3
// 4

辅助迭代器
ES5中的一些数组的辅助迭代器:
forEach

const array = [1, 2, 3, 4]
array.forEach((item) => {
        console.log(item); //1,2,3,4
      });

some

array.some((item) => {
        console.log(item); //1,2,3,4
      	return false
	  });

every

array.every((item) => {
        console.log(item); //1,2,3,4
      	return true
	  });

some和every的区别:some是当返回值有一个是返回true就结束遍历,every是当返回值有一个是false的时候结束遍历
forEach没有返回值
手动遍历
使用es6的symbol类型,Symbol.iterator可以获取对象的内部属性,然后可以带有next()方法,返回的是一个{value, done},value是值,done是当前是否到了底部

      const array = [1, 2, 3, 4];
      const it = array[Symbol.iterator]();
      console.log(it.next());// {value: 1, done: false}
      console.log(it.next());// {value: 2, done: false}
      console.log(it.next());// {value: 3, done: false}
      console.log(it.next());// {value: 4, done: false}
      console.log(it.next());// {value: undefined, done: true}
posted @ 2021-08-05 12:45  卿六  阅读(34)  评论(0编辑  收藏  举报