JS对象详解

对象是包括属性与方法的数据类型,JS中大部分类型都是对象,如:String、Boolean、Symbol、Number、BigInt、Object、Array、RegExp、Date、Function等等。

一、对象计算

对象直接参与计算时,系统会根据计算的场景在 string/number/default 间转换。

对象内部自定义 Symbol.toPrimitive、valueOf、toString方法用来处理所有的转换场景。

  • [Symbol.toPrimitive] 优先级最高,如果这个方法存在,其他两个方法将不会查找
  • 如果没有[Symbol.toPrimitive]方法,则算术运算和条件比较时valueOf的优先级会高一些
  • 如果没有[Symbol.toPrimitive]方法,则字符串拼接操作时toString的优先级会高一些
    var o = {
     /*  [Symbol.toPrimitive]: function () {
        return 10;
      }, */
      valueOf: function () {
        return 100;
      },
      toString: function () {
        return '[object Object]';
      }
    };

    console.log(o + 1);
    console.log(o == 100);
    console.log(`字符串拼接${o}`);

注意: Symbol.toPrimiative是一个变量,必须加上[ ]

二、对象解构赋值

1、基本使用

解构原则:看右边,如果是对象则key相同,如果是数组,名称随意,左右类型相同。

//对象解构
    var o={id:1000,title:'phone',price:999};
    var {id,title,price} = o;
    console.log(id,title,price);
//数组解构
    var arr = ["10", "100", "1000"];
    var [a, b, c] = arr;
    console.log(a,b,c);

//解构练习
    var obj = { id: 1, child: [1, 2, 3, { tag: 'div' }] }
    var {id,child:[,,c,{tag}]} = obj;
    console.log(id,c,tag);

2、默认值解构

注:解构时 : 是给原来的key值起别名,= 是给变量赋值默认值

//对象
    var obj = { title: '标题' };
    var { title: name, url = "http://www.baidu.com" } = obj;
    console.log(name, url);
//数组
    var arr=[100,1000];
    var [a,b,c=1001]=arr;
    console.log(a,b,c);

对象的解构赋值,多用于封装函数时,函数的形参太多,这时使用对象传入形参的形式进行解构赋值,可以不用规定形参实参的顺序,且当有利于设置默认值。

//方法1:
    function fn({
      id = 1,
      name = "zhangsan",
      age
    }) {
      console.log(id,name,age);
    }

//方法二:
    function fn(options) {
      let { id = 1, name = "zhangsan", age } = options;
      console.log(id, name, age);
    }

//方法三:...语法
   function fn(options) {
      let obj = { ...options, name:"lisi", id:2 };
      console.log(obj);
    }


	fn({ age: 18 });

三、属性管理

1、添加属性

    let obj = {id:1,name:"zhangsan"};
    obj.age = 18;
    console.log(obj);

2、删除属性

使用delete关键字

    let obj = {id:1,name:"zhangsan"};
    obj.age = 18;
    delete obj.name;
    console.log(obj);

3、检测属性

属性:公有属性(原型和原型链上的)和私有属性(构造方法中的)
此处的公有私有区别于后端语言中的公有私有


hasOwnProperty 检差指定名称是否是当前对象的私有属性,不检测原型链上继承的属性。

in 关键词可以用来检查公有属性,先检查私有,私有中没有继续检查共有属性,他会在__proto__(原型链)中找

    let obj = {id:1,name:"zhangsan"};
    console.log(obj.hasOwnProperty('id'));
    console.log("id" in obj);

检查当前给定属性是否为公有属性

    function isPublic(obj,prop){
      return obj.hasOwnProperty(prop)&&prop in obj;
    }

    console.log(isPublic(obj,name));

4、获取属性名

Object.getOwnPropretyNames 获取对象中所有非Symbol类型的私有属性方法,以数组的形式返回。
等同于 Object.keys

    let sym=Symbol();
    let obj1={id:1,name:"lisi",[sym]:'唯一值'};
    console.log(Object.keys(obj1));
    console.log(Object.getOwnPropertyNames(obj1));

Object.getOwnPropertySymbols 只获取Symbol的私有属性方法,以数组的形式返回

    let sym=Symbol();
    let obj1={id:1,name:"lisi",[sym]:'唯一值'};
    console.log(Object.getOwnPropertySymbols(obj1));

结合上述两种方法遍历出对象中所有的私有属性方法

    let sym = Symbol();
    let obj1 = { id: 1, name: "lisi", [sym]: '唯一值' };
    let keys = [...Object.getOwnPropertyNames(obj1), ...Object.getOwnPropertySymbols(obj1)];
    keys.forEach(item => {
      console.log(item, obj1[item]);
    })

5、禁止向对象中添加属性

禁止了向对象中添加新属性,但还是可以对原有的属性进行数据修改。

在严格模式下,禁止给对象添加属性设置后,如果你还添加属性,则报错,后续代码不会执行。

语法:Object.preventExtensions()

    // 'use strict'
    let sym = Symbol();
    let obj1 = { id: 1, name: "lisi", [sym]: '唯一值' };
    Object.preventExtensions(obj1);
    obj1.a = 10;	//严格模式下会报错且后续代码不执行
    obj1.id = 10;
    console.log(obj1);
    console.log(1);

6、冻结对象

冻结对象,相当于把对象定义为一个常量。

严格模式下,如果对已冻结的对象修改或添加属性则报错,后续代码不会执行。

非严格模式下,不会报错,修改或添加属性没有效果。

冻结对象 语法: Object.freeze()

检查当前对象是否为冻结对象 true/false,语法:Object.isFrozen()

    // 'use strict'
    let sym = Symbol();
    let obj1 = { id: 1, name: "lisi", [sym]: '唯一值' };
    Object.freeze(obj1);
    console.log(Object.isFrozen(obj1));	//true
    obj1.id=10;	//严格模式下报错,终止后续代码执行
    console.log(obj1);

7、修改器和获取器

修改器:set

获取器:get

调用时,不能把它们当做方法,应该当做属性。es6+语法

通过修改器和获取器,可以在对象内部对属性值进行处理。

    let obj = {
      //私有属性
      _id: 1000,
      get id() {
        //写条件
        return this._id > 500 ? '优秀' : this._id;
      },
      set id(value) {
        //写条件
        value = isNaN(Number(value)) ? 0 : Number(value);
        this._id = value;
      }
    };
    obj.id='300a';
    console.log(obj.id);

对象属性私有化:
比如在项目的一些配置文件,不能让别人修改,设置属性的key为Symbol型,把该对象暴露在外面时,无法通过该对象的key直接获取和修改value,只能通过修改器和获取器来修改或者获取,我们在修改器和获取器中添加条件,可以保证数据的合法性。

    let _idsy=Symbol('id');
    let obj={
      [_idsy]:1000,
      get id() {
        //写条件
        return this[_idsy] > 500 ? '优秀' : this._id;
      },
      set id(value) {
        //写条件
        value = isNaN(Number(value)) ? 0 : Number(value);
        this[_idsy] = value;
      }
    }

四、复制对象

Object.assign(目标,源1,源2…) 把源1,源2这些对象合并到目标对象上,并且把目标对象返回,目标对象的地址和源1、源2等地址不关联。

    var o1 = { a: 1, b: 2 };
    var o2 = { c: 3 };
    var o3 = { a: 10, d: 4 };
    Object.assign(o1, o2, o3);
    o2.c = 1000;	//引用地址不关联
    console.log(o1);

浅拷贝:

方法1:使用Object.assign方法

    var o1 = { a: 1, b: 2 };
    var o2 = Object.assign({}, o1);
    o1.b = 100;
    console.log(o2);

方法2:for in 循环遍历

    var o1 = { a: 1, b: 2 };
    var o2={};
    for(let prop in o1){
    	//是o1的私有属性则复制
    	if(o1.hasOwnProperty(prop)) o2[prop]=o1[prop];
    };
    o1.b=1000;
    console.log(o2);

方法3:for of 循环

Object.entries() 这个方法能以二维数组的方式返回对象的key和value

    var o1 = { a: 1, b: 2 };
    var o2={};
    for(let [key,value] of Object.entries(o1)){
      o2[key] = value;
    };

方法4:展开运算法 …语法

    var o1 = { a: 1, b: 2 };
    var o2={...o1};
    console.log(o2);

深拷贝

    function deepClone(obj){
      //判断obj是不是对象
      if(typeof obj !== 'object') return obj;
      //判断obj是数组还是对象
      let target= 'push' in obj ? [] : {};
      for(let [key,value] of Object.entries(obj)){
        target[key] = typeof value === 'object' ? deepClone(value) : value;
      }
      return target;
    }

五、Object.create

创建一个空对象,基于传入的对象创建一个新对象(和传入的对象没有引用关系),将空对象的__proto__ 属性指向新创建的对象

    var o = {a:1};
    var o2= {b:2};
    console.log(Object.create(o2));
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值