对象密封的4种方法

image.png

  1. const obj={
  2. get foo(){
  3. },
  4. set foo() {
  5. //SyntaxError: Setter must have exactly one formal parameter.
  6. /*set方法必须有参数*/
  7. }
  8. }
  9. console.log(obj.foo);
  1. const obj = {
  2. get foo() {
  3. },
  4. set foo(x) {
  5. }
  6. }
  7. console.log(obj.foo);//undefined
  8. /*通过对象.属性的方式并不能获取当前的取值get(getter)函数和储存set(setter)函数*/
  1. const obj = {
  2. get foo() {
  3. },
  4. set foo(x) {
  5. }
  6. }
  7. console.log(obj.foo);//undefined
  8. console.log(obj);

image.png

  1. const obj = {
  2. get foo() {
  3. },
  4. set foo(x) {
  5. }
  6. }
  7. console.log(obj.foo);//undefined
  8. // console.log(obj);
  9. console.log(Object.getOwnPropertyDescriptor(obj,'foo'));

image.png

  1. const obj = {
  2. get foo() {
  3. },
  4. set foo(x) {
  5. }
  6. }
  7. /* console.log(obj.foo);//undefined
  8. // console.log(obj);
  9. console.log(Object.getOwnPropertyDescriptor(obj,'foo'));*/
  10. var descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');
  11. console.log(descriptor);
  12. console.log(descriptor.get.name)//get foo
  13. console.log(descriptor.get)//
  14. console.log(descriptor.set.name)//set foo
  15. console.log(descriptor.set)//

image.png

  1. var obj = {a: 2};
  2. console.log(Object.prototype);

image.png

1.对象常量:configurable:fase writeable:false; 不可删除,不可修改;
还需要一个不可以添加,不可以扩展

  1. var obj = {a: 2};
  2. // var test=Object.preventExtensions(obj);/*让obj对象不能扩展*/
  3. Object.preventExtensions(obj);/*让obj对象不能扩展*/
  4. // console.log(test===obj);//true
  5. obj.b=3;
  6. console.log(Object.isExtensible(obj));//false 不可扩展 true可扩展
  7. console.log(obj);//{a: 2}

严格模式下会报错
image.png

  1. var obj = {a: 2};
  2. obj.b = 3;//属性描述符,全都是true
  3. /*{ value: 3, writable: true, enumerable: true, configurable: true }
  4. * 属性描述符,全都是true*/
  5. /*Object.defineProperty(obj, 'b', {
  6. value: 6
  7. })*/
  8. /*属性描述符,默认是false
  9. * { value: 6, writable: false, enumerable: false, configurable: false }
  10. */
  11. console.log(Object.getOwnPropertyDescriptor(obj, 'b'));
  12. console.log(obj);//{a: 2}

2.preventExtensions禁止对象扩展;false不可扩展 true可扩展

3.seal 对象的密封 true密封的 false不密封的
本质上是在做一个调用prevent extension这件事情,它会有一个循环操作,把循环到的属性,把属性配置成configurable等于false

4.Object.freeze();

time36min
kl

相等的扩展

  1. /*相等运算符*/
  2. console.log(NaN==NaN);//false
  3. console.log(+0==-0);//true
  4. /*严格相等运算符*/
  5. console.log(NaN===NaN);//false
  6. /*这种情况并不合理,如果判断两个非数字,一般是转换成字符串再去判断的*/
  7. console.log(+0===-0);//true
  8. /*===会调用 底层的一个叫做sameValue的算法,来判断,不是方法,也会出现NaN===NaN false的现象*/
  9. /*==会进行转换,隐式转换*/
  1. console.log(Object.is(NaN,NaN));//true
  2. console.log(Object.is(+0,-0));//false
  3. /*Object.is(val1,val2)底层调用的还是===,只不过以上两个的结果与===不同,其它的结果相同*/

image.png

Object.assign()

用来合并一个对象的,

es5 extend()类似的方法
Object.assign(tar,…sourses)

  1. let obj = {a: 1};
  2. let tar = {};
  3. let copy=Object.assign(tar,obj);
  4. console.log(copy)//{ a: 1 }
  5. console.log(copy===obj);//false
  6. console.log(copy===tar);//true


所以一般就是tar不用赋值,因为接收的变量,方法返回值就是经过改变的第一个变量的值,的地址

  1. let obj = {a: 1};
  2. let tar = {};
  3. Object.assign(tar,obj);
  4. //let copy=Object.assign(tar,obj);
  5. console.log(tar)//{ a: 1 }
  1. const tar = {a: 1, b: 1};
  2. const tar2 = {b: 2,c : 2};
  3. const tar3 = {c: 3};
  4. Object.assign(tar, tar2, tar3);//{ a: 1, b: 2, c: 3 }
  5. /*类似于以下代码*/
  6. // Object.assign(Object.assign(tar, tar2), tar3);//{ a: 1, b: 2, c: 3 }
  7. console.log(tar);//{ a: 1, b: 2, c: 3 }
  8. /*后面的会覆盖前面的*/
  1. Object.assign(undefined, {a: 1});
  2. //TypeError: Cannot convert undefined or null to object
  1. Object.assign(null, {a: 1});
  2. // TypeError: Cannot convert undefined or null to object
  1. var test=Object.assign(1, {a: 1});
  2. // var test=Object.assign(new Number(1), {a: 1});
  3. console.log(test);//[Number: 1] { a: 1 }

image.png
把1通过new Number(1)转换成对象

  1. var test=Object.assign('1', {a: 1});
  2. var test=Object.assign(new String('1'), {a: 1});
  3. console.log(test);//String{'1', a: 1}
  1. var test=Object.assign({a: 1},undefined);
  2. console.log(test);//{a: 1}
  1. var test=Object.assign({a: 1},1);
  2. console.log(test);//{a: 1}
  1. var test=Object.assign({a: 1},'123');
  2. console.log(test);//{0: '1', 1: '2', 2: '3', a: 1}
  1. var test=Object.assign({a: 1},'1');
  2. console.log(test);//{0: '1', a: 1}
  1. var test=Object.assign({a: 1},true);
  2. console.log(test);//{a: 1}

当前的参数如果能够转成对象的话,注意对象里面的属性是否是可枚举性的,可枚举性是否为真,为真才能完成拷贝
对第二个参数应该注意以上内容

  1. const test1 = 'abc';
  2. const test2 = true;
  3. const test3 = 10;
  4. const obj = Object.assign({}, test1, test2, test3);
  5. console.log(obj);//{0: 'a', 1: 'b', 2: 'c'}
  1. console.log(new Object('abc'));

image.png

  1. console.log(new Object('abc'));
  2. console.log(new Boolean(true));
  3. console.log(new Number(10));
  1. const test1 = 'abc';
  2. const test2 = true;
  3. const test3 = 10;
  4. // const obj = Object.assign({}, test1, test2, test3);
  5. const obj = Object.assign({}, test1);//{0: 'a', 1: 'b', 2: 'c'}
  6. // const obj = Object.assign({}, test2);//{}
  7. // const obj = Object.assign({}, test3);//{}
  8. console.log(obj);//{0: 'a', 1: 'b', 2: 'c'}

可以枚举的才可以, enumerable: true,这个属性默认是false
继承属性,和不可枚举属性 不能拷贝

  1. var obj = Object.create({foo: 1}, {
  2. bar: {
  3. value: 2
  4. },
  5. baz: {
  6. value: 3,
  7. enumerable: true
  8. }
  9. })
  10. console.log(obj);//{baz: 3, bar: 2}
  11. var copy=Object.assign({},obj);
  12. console.log(copy);//{baz: 3}

image.png

symbol

  1. var a = Symbol();
  2. var b = Symbol();
  3. console.log(a,b);//Symbol() Symbol()
  4. console.log(a===b);//false
  5. console.log(a==b);//false
  1. var a = Symbol('a');
  2. var b = Symbol('a');
  3. console.log(a,b);//Symbol(a) Symbol(a)
  4. console.log(a===b);//false
  5. console.log(a==b);//false

可以通过symbol方法生成一个类似于字符串的一个原始类型,可以先看作一个值不会重复的字符串
symbol返回的字符串都不会重复

  1. var test = Object.assign({a: 'b'}, {[Symbol('c')]:'d'});
  2. console.log(test);

image.png
通过assign,也可以合并symbol生成的属性,symbol类型的属性也能进行拷贝

深拷贝还是浅拷贝,浅拷贝

  1. const obj1 = {a: {b: 1}};
  2. const obj2 = Object.assign({}, obj1);
  3. obj1.a.b = 2;
  4. console.log(obj2);//浅拷贝的对象 是浅拷贝

image.png

  1. const target = {a: {b: 'c', d: 'e'}};
  2. const sourse = {a: {b: 'hello'}};
  3. /*a:{..}把a:{..}里面的内容全部替换掉了*/
  4. Object.assign(target,sourse);
  5. console.log(target);//同名属性的替换问题

image.png

  1. var a = Object.assign([1, 2, 3], [4, 5]);
  2. console.log(a);//[4, 5, 3]
  1. var a = Object.assign([1, 2, 3], [4, 5]);
  2. console.log(a);//[4, 5, 3] 数组的替换
  1. const sourse = {
  2. get foo() {
  3. return 1;
  4. }
  5. }
  6. const target = {};
  7. Object.assign(target, sourse);
  8. console.log(target);//{foo: 1}

这个拷贝方式并不合适,不好
只是把foo属性值,把返回的值1拿到并没有把get foo的一切都拿到,一会会有解决方法

通过assign方法扩充Person原型上的属性

  1. var age=1;
  2. function Person() {
  3. }
  4. Object.assign(Person.prototype,{
  5. eat(){
  6. },
  7. age,
  8. })
  9. console.log(Person.prototype)
  10. console.log(Person)

image.png

  1. // const default1 = {//可以
  2. const DEFAULT = {//可以
  3. // const default = {//Uncaught SyntaxError: Unexpected token 'default'
  4. url: "www.baidu.com",
  5. port: 7070
  6. }
  7. function test(option) {
  8. // option = Object.assign({}, DEFAULT);
  9. option = Object.assign({}, DEFAULT, option);
  10. console.log(option);
  11. }
  12. test({url: {port: 8080}})//{url: 'www.baidu.com', port: 7070}
  13. /*默认值,修改默认值,把默认url整个顶掉*/

defineProperties添加定义多个属性

  1. var obj = {};
  2. Object.defineProperties(obj, {
  3. a: {
  4. value: true,
  5. writable: true
  6. },
  7. b:{
  8. value: 'hello',
  9. writable: false
  10. }
  11. })
  12. console.log(obj);
  13. console.log(Object.getOwnPropertyDescriptors(obj));

image.png

assign与set:assign不能拷贝set,只能拷贝set返回的值

  1. const sourse = {
  2. set foo(value) {
  3. console.log(value);
  4. }
  5. }
  6. const tar = {};
  7. Object.assign(tar,sourse);
  8. console.log(tar);

assign不能给set赋值

解决方法,可运算属性完成赋值

getOwnPropertyDescriptors、defineProperties这两个方法主要是为了解决这个问题而存在的

  1. const sourse = {
  2. set foo(value) {
  3. console.log(value);
  4. }
  5. }
  6. const tar = {};
  7. // Object.assign(tar, sourse);
  8. Object.defineProperties(tar,Object.getOwnPropertyDescriptors(sourse));
  9. console.log(tar);//
  10. console.log(Object.getOwnPropertyDescriptor(tar,'foo'));

image.png

这样不行,assign拷贝不了get set

  1. const sourse = {
  2. set foo(value) {
  3. console.log(value);
  4. }
  5. }
  6. const tar = {};
  7. Object.assign(tar, sourse);
  8. // Object.defineProperties(tar,Object.getOwnPropertyDescriptors(sourse));
  9. console.log(tar);//
  10. console.log(Object.getOwnPropertyDescriptor(tar,'foo'));

image.png

实现浅拷贝

  1. var obj = {a: 1, b: 2, c: 3};
  2. const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
  3. /*Object.getPrototypeOf(obj)得到obj的原型
  4. *Object.getOwnPropertyDescriptors(obj)获取obj上面所有属性,克隆obj上面的属性 */
  5. console.log(clone);//{a: 1, b: 2, c: 3}

封装

  1. var obj = {a: 1, b: 2, c: 3};
  2. // const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));
  3. /*Object.getPrototypeOf(obj)得到obj的原型
  4. *Object.getOwnPropertyDescriptors(obj)获取obj上面所有属性,克隆obj上面的属性 */
  5. const clone = (obj) => Object.create(
  6. Object.getPrototypeOf(obj),
  7. Object.getOwnPropertyDescriptors(obj)
  8. )
  9. // console.log(clone);//{a: 1, b: 2, c: 3}
  10. console.log(clone(obj));//{a: 1, b: 2, c: 3}

这是新增api,但不讲不行,用的相对少一点,但解决方案是唯一的

部署对象

  1. 1. const obj = {a:1}
  2. 2. const obj = Object.create(prototype);
  3. obj.foo = 123;
  4. 3. const obj = Object.assign(Object.create(prototype),{foo:123});
  5. 4. const obj = Object.create(prototype,Object.getOwnPropertyDescriptors({
  6. foo:123
  7. }));