• ES6中对象的扩展


    1. 属性的简洁表示法

    可以直接写入变量和函数作为对象的属性和方法。在对象中只写属性名,不写属性值,代表属性值等于和属性名相同的的变量的值。

    属性的简写

    
    let foo = 'bar';
    let baz = {foo}; // { foo: 'bar' }
    // 等同于
    let baz = { foo: foo}
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    方法的简写

    let o = {
    	method: function() {
    		return 'hello';
    	}
    }
    
    let o = {
    	method() {
    		return 'hello';
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    好处:

    • 函数返回会很方便
    • 书写很方法
    • CommonJS输出变量会很方便

    如果某个方法的值是一个Generator函数,则前面需要加上星号。

    const obj = {
    	* m() {
    		yield 'hello world';	
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    2. 属性名表达式

    在js之前对象定义属性名可以使用标识符或者表达式。但是如果使用字面量定义对象(大括号),只能使用标识符定义,不能使用表达式。

    之前写法

    // 标识符定义
    obj.foo = true;
    // 表达式定义
    obj['a'+ 'b'] = 123;
    
    • 1
    • 2
    • 3
    • 4

    在ES6中在定义对象时表达式可以定义属性名、方法名。

    但是属性名表达式不能与简洁表示法一起使用,否则会报错。

    // 定义在对象中
    let propKey = 'foo';
    let obj = {
    	[propKey]: true,
    	['a' + 'b']: 123,
    }
    
    // 定义在方法
    let a = {
    	'first word': 'hello',
    	['a'+'b'](){
    		return 'hi';	
    	}
    }
    
    // 不能与简洁表示法一块使用
    let foo = 'bar';
    let baz = { [foo] }; // 会报错
    // 可以这样写
    let baz = { [foo]: foo }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    注意:如果属性表达式是一个对象,默认情况下会自动转为字符串[object Object],这样就要特别注意!

    const keyA = { a: 1};
    const keyB = { b: 2};
    const myObject = {
        [keyA]: 'valueA',
        [keyB]: 'valueB',
    }
    console.log(myObject);  // [object Object]: 'valueB'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    这是因为这两个属性名都是对象,都转成同一个属性名[object Object],所以就把上面的属性自动覆盖掉了,不能有相同名称的属性名。

    3. 方法的name属性

    函数的name属性返回函数名,方法也是函数,也有name属性并返回函数名即方法名。

    const person = {
    	sayName() {
    		console.log('hello');	
    	}
    }
    person.sayName.name // 'sayName'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    对于方法使用了get、set函数,则name属性不在该方法上。则在方法属性的描述对象的get和set属性上,返回值会在方法名前加上get和set。

    如何操作获取含有get、set的方法名?

    1. 首先可以使用Object.getOwnPropertyDescriptor()方法,获取该属性的描述对象。
    2. 然后在使用`name`属性获取方法名。
    const obj = {
    	get foo() {},
    	set foo(x) {}
    }
    obj.foo.name; // 会报错
    
    const descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
    descriptor.get.name; // 'get foo'
    descriptor.set.name; // 'get foo'
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    特殊情况!bind方法创造的函数,name属性返回值会在函数名的前面加上bound;Function构造函数创造的函数,name属性返回anonymous

    (new Function()).name // 'anonymous'
    
    const doSomething = function(){}
    doSomething.bind().name // 'bound doSomething'
    
    • 1
    • 2
    • 3
    • 4

    如果对象的方法是一个Symbol值,那么属性返回的是这个Symbol值的描述。

    4. Object.is()

    用来比较两个值是否严格相等,与严格相等运算符(===)的行为一致。返回布尔类型

    两个不同的是,+0不等于-0,NaN等于自身

    Object.is('foo', 'foo'); // true
    
    Object.is(NaN, NaN); // true
    Object.is(+0, -0); // false
    
    • 1
    • 2
    • 3
    • 4

    为什么ES6要提供Object.is方法?

    因为在ES5中比较两个值是否相等,只有相等运算符()和严格相等运算符(=)两种,但他们有个缺点,前者在比较时会自动转换数据类型,后者在比较时,NaN不等于自身,+0等于-0,造成js中缺少一种运算,就是在所有环境中,只要两个值是一样的,它们就应该相等。所有在ES6中提出了Same-value equality(同值相等)算法来解决这个问题。

    如何在ES5中模拟Object.is

    Object.defineProperty(Object, 'is', {
    	value: function(x, y) {
    		if(x === y) {
    			// 针对+0 不等于-0的情况
    			return x !== 0 || 1 / x === 1 /y; 
    		}
    		// 针对NaN的情况
    		return x !== x && y !== y;
    	},
    	configurable: true,
    	enumerable: false,
    	writable: true
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    5. Object.assign()

    用于将源对象的所有可枚举属性复制到目标对象。

    第一个参数:目标对象。后面的参数都是源对象,后面的参数可以为多个。

    let target = { a: 1};
    let source1 = { b: 2};
    let source2 = { c: 3};
    Object.assign(target, source1, source2);
    target // { a: 1, b: 2, c: 3 }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注意点

    • 如果目标对象中与源对象有同名属性,则后面的属性会覆盖前面的属性。
    • 如果只有一个参数,也就是目标对象,Object.assgin会直接返回该参数。如果不是对象,会先转成对象,然后返回。由于undefined和null无法转成对象,所以会报错
    typeof Object.assign(2); // 'object'
    Object.assign(undefined); // 报错
    
    • 1
    • 2
    • 如果非对象出现在源对象的位置,会先转对象,无法转的会先跳过,这意味着undefined和null不会报错。
    let obj = {a: 1};
    Object.assign(obj, undefined) === obj; // true
    
    
    • 1
    • 2
    • 3
    • 数值、字符串和布尔值在源对象中,不会报错,字符串会以数组形式复制到目标对象中,其他值直接跳过
    const obj = Object.assign({}, 12, true, 'ab'); // {'0': 'a', '1': 'b'}
    
    
    • 1
    • 2

    可以看出转成对象后,它们的原始值都会包装在对象的内部属性[[PrimitiveValue]]上面,这个属性是不会被Object.assign复制的。只有字符串的包装对象会产生可枚举的实义属性,才会被拷贝

    • Object.assign只会对源对象自身属性拷贝,不会复制继承过来的属性,也不会复制不可枚举的属性。
    • 属性名也Symbol值的属性也会被复制
    Object.assign({a: 'b'}, {[Symbol('c')]: 'd'});
    // { a: 'b', Symbol(c): 'd'}
    
    • 1
    • 2
    • 复制是浅拷贝不是深拷贝

    用途

    • 为对象添加属性
    • 为对象添加方法
    • 克隆对象

    把一个原始对象复制到一个空对象中

    • 合并多个对象
    • 为属性指定默认值

    6. 属性的可枚举性

    对象的每一个属性都具有一个描述对象,用来控制属性的行为,使用Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。

    let obj = { foo: 123 };
    Object.getOwnPropertyDescriptor(obj);
    /**
    	{
    	
    		value: 123,
    		writable: true,
    		enumerable: true,
    		configurable: true
    	}
    
    */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    enumerable属性称为可枚举性,若属性值为true,则可以枚举,为false则不能,遍历时会忽略。

    会忽略enumerable为false属性的操作,在ES5中有3个,ES6又新增了一个。

    • for…in循环:只遍历对象自身和继承过来的可枚举属性
    • Object.keys():返回对象自身可枚举属性的键名
    • JSON.stringify():只串行化对象自身的可枚举属性
    • Object.assign():遍历对象自身可枚举的属性

    7. 属性的遍历

    共有5中方法

    • for … in

    只遍历对象自身和继承过来的可枚举属性

    • Object.keys(obj)

    返回一个数组,包括对象自身可枚举属性的键名

    • Object.getOwnPropertyNames(obj)
  • 相关阅读:
    网友咨询:手机卡套餐可以换成流量卡套餐吗?说一说改套餐的问题!
    2023.10.18 信息学日志
    神经网络解决哪些问题,神经网络结果不稳定
    数据⼀致性模型有哪些?
    xampp安装包含的组件有(php,perl,apche,mysql)
    小伙伴说VuePress太简洁了,还有没有其他博客推荐?
    数据中心的黑科技——到底什么是NPO/CPO?
    SpringCloudAlibaba实战入门之手把手教你创建第一个SpringCloudAlibaba项目(三)
    MQ系列7:消息通信,追求极致性能
    android 创建桌面快捷方式 ShortCut
  • 原文地址:https://blog.csdn.net/zsm4623/article/details/133563245