对象密封的4种方法

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

const obj = {get foo() {},set foo(x) {}}console.log(obj.foo);//undefined// console.log(obj);console.log(Object.getOwnPropertyDescriptor(obj,'foo'));

const obj = {get foo() {},set foo(x) {}}/* console.log(obj.foo);//undefined// console.log(obj);console.log(Object.getOwnPropertyDescriptor(obj,'foo'));*/var descriptor = Object.getOwnPropertyDescriptor(obj, 'foo');console.log(descriptor);console.log(descriptor.get.name)//get fooconsole.log(descriptor.get)//console.log(descriptor.set.name)//set fooconsole.log(descriptor.set)//

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

1.对象常量:configurable:fase writeable:false; 不可删除,不可修改;
还需要一个不可以添加,不可以扩展
var obj = {a: 2};// var test=Object.preventExtensions(obj);/*让obj对象不能扩展*/Object.preventExtensions(obj);/*让obj对象不能扩展*/// console.log(test===obj);//trueobj.b=3;console.log(Object.isExtensible(obj));//false 不可扩展 true可扩展console.log(obj);//{a: 2}
严格模式下会报错
var obj = {a: 2};obj.b = 3;//属性描述符,全都是true/*{ value: 3, writable: true, enumerable: true, configurable: true }* 属性描述符,全都是true*//*Object.defineProperty(obj, 'b', {value: 6})*//*属性描述符,默认是false* { value: 6, writable: false, enumerable: false, configurable: false }*/console.log(Object.getOwnPropertyDescriptor(obj, 'b'));console.log(obj);//{a: 2}
2.preventExtensions禁止对象扩展;false不可扩展 true可扩展
3.seal 对象的密封 true密封的 false不密封的
本质上是在做一个调用prevent extension这件事情,它会有一个循环操作,把循环到的属性,把属性配置成configurable等于false
4.Object.freeze();
time36min
kl
相等的扩展
===
/*相等运算符*/console.log(NaN==NaN);//falseconsole.log(+0==-0);//true/*严格相等运算符*/console.log(NaN===NaN);//false/*这种情况并不合理,如果判断两个非数字,一般是转换成字符串再去判断的*/console.log(+0===-0);//true/*===会调用 底层的一个叫做sameValue的算法,来判断,不是方法,也会出现NaN===NaN false的现象*//*==会进行转换,隐式转换*/
console.log(Object.is(NaN,NaN));//trueconsole.log(Object.is(+0,-0));//false/*Object.is(val1,val2)底层调用的还是===,只不过以上两个的结果与===不同,其它的结果相同*/

Object.assign()
用来合并一个对象的,
es5 extend()类似的方法
Object.assign(tar,…sourses)
let obj = {a: 1};let tar = {};let copy=Object.assign(tar,obj);console.log(copy)//{ a: 1 }console.log(copy===obj);//falseconsole.log(copy===tar);//true
所以一般就是tar不用赋值,因为接收的变量,方法返回值就是经过改变的第一个变量的值,的地址
let obj = {a: 1};let tar = {};Object.assign(tar,obj);//let copy=Object.assign(tar,obj);console.log(tar)//{ a: 1 }
const tar = {a: 1, b: 1};const tar2 = {b: 2,c : 2};const tar3 = {c: 3};Object.assign(tar, tar2, tar3);//{ a: 1, b: 2, c: 3 }/*类似于以下代码*/// Object.assign(Object.assign(tar, tar2), tar3);//{ a: 1, b: 2, c: 3 }console.log(tar);//{ a: 1, b: 2, c: 3 }/*后面的会覆盖前面的*/
Object.assign(undefined, {a: 1});//TypeError: Cannot convert undefined or null to object
Object.assign(null, {a: 1});// TypeError: Cannot convert undefined or null to object
var test=Object.assign(1, {a: 1});// var test=Object.assign(new Number(1), {a: 1});console.log(test);//[Number: 1] { a: 1 }

把1通过new Number(1)转换成对象
var test=Object.assign('1', {a: 1});var test=Object.assign(new String('1'), {a: 1});console.log(test);//String{'1', a: 1}
var test=Object.assign({a: 1},undefined);console.log(test);//{a: 1}
var test=Object.assign({a: 1},1);console.log(test);//{a: 1}
var test=Object.assign({a: 1},'123');console.log(test);//{0: '1', 1: '2', 2: '3', a: 1}
var test=Object.assign({a: 1},'1');console.log(test);//{0: '1', a: 1}
var test=Object.assign({a: 1},true);console.log(test);//{a: 1}
当前的参数如果能够转成对象的话,注意对象里面的属性是否是可枚举性的,可枚举性是否为真,为真才能完成拷贝
对第二个参数应该注意以上内容
const test1 = 'abc';const test2 = true;const test3 = 10;const obj = Object.assign({}, test1, test2, test3);console.log(obj);//{0: 'a', 1: 'b', 2: 'c'}
console.log(new Object('abc'));

console.log(new Object('abc'));console.log(new Boolean(true));console.log(new Number(10));
const test1 = 'abc';const test2 = true;const test3 = 10;// const obj = Object.assign({}, test1, test2, test3);const obj = Object.assign({}, test1);//{0: 'a', 1: 'b', 2: 'c'}// const obj = Object.assign({}, test2);//{}// const obj = Object.assign({}, test3);//{}console.log(obj);//{0: 'a', 1: 'b', 2: 'c'}
可以枚举的才可以, enumerable: true,这个属性默认是false
继承属性,和不可枚举属性 不能拷贝
var obj = Object.create({foo: 1}, {bar: {value: 2},baz: {value: 3,enumerable: true}})console.log(obj);//{baz: 3, bar: 2}var copy=Object.assign({},obj);console.log(copy);//{baz: 3}
symbol
var a = Symbol();var b = Symbol();console.log(a,b);//Symbol() Symbol()console.log(a===b);//falseconsole.log(a==b);//false
var a = Symbol('a');var b = Symbol('a');console.log(a,b);//Symbol(a) Symbol(a)console.log(a===b);//falseconsole.log(a==b);//false
可以通过symbol方法生成一个类似于字符串的一个原始类型,可以先看作一个值不会重复的字符串
symbol返回的字符串都不会重复
var test = Object.assign({a: 'b'}, {[Symbol('c')]:'d'});console.log(test);

通过assign,也可以合并symbol生成的属性,symbol类型的属性也能进行拷贝
深拷贝还是浅拷贝,浅拷贝
const obj1 = {a: {b: 1}};const obj2 = Object.assign({}, obj1);obj1.a.b = 2;console.log(obj2);//浅拷贝的对象 是浅拷贝

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

var a = Object.assign([1, 2, 3], [4, 5]);console.log(a);//[4, 5, 3]
var a = Object.assign([1, 2, 3], [4, 5]);console.log(a);//[4, 5, 3] 数组的替换
const sourse = {get foo() {return 1;}}const target = {};Object.assign(target, sourse);console.log(target);//{foo: 1}
这个拷贝方式并不合适,不好
只是把foo属性值,把返回的值1拿到并没有把get foo的一切都拿到,一会会有解决方法
通过assign方法扩充Person原型上的属性
var age=1;function Person() {}Object.assign(Person.prototype,{eat(){},age,})console.log(Person.prototype)console.log(Person)

// const default1 = {//可以const DEFAULT = {//可以// const default = {//Uncaught SyntaxError: Unexpected token 'default'url: "www.baidu.com",port: 7070}function test(option) {// option = Object.assign({}, DEFAULT);option = Object.assign({}, DEFAULT, option);console.log(option);}test({url: {port: 8080}})//{url: 'www.baidu.com', port: 7070}/*默认值,修改默认值,把默认url整个顶掉*/
defineProperties添加定义多个属性
var obj = {};Object.defineProperties(obj, {a: {value: true,writable: true},b:{value: 'hello',writable: false}})console.log(obj);console.log(Object.getOwnPropertyDescriptors(obj));

assign与set:assign不能给set赋值,只能拷贝set返回的值
const sourse = {set foo(value) {console.log(value);}}const tar = {};Object.assign(tar,sourse);console.log(tar);
assign不能给set赋值
解决方法,可运算属性完成赋值
getOwnPropertyDescriptors、defineProperties这两个方法主要是为了解决这个问题而存在的
const sourse = {set foo(value) {console.log(value);}}const tar = {};// Object.assign(tar, sourse);Object.defineProperties(tar,Object.getOwnPropertyDescriptors(sourse));console.log(tar);//console.log(Object.getOwnPropertyDescriptor(tar,'foo'));

这样不行,assign拷贝不了get set
const sourse = {set foo(value) {console.log(value);}}const tar = {};Object.assign(tar, sourse);// Object.defineProperties(tar,Object.getOwnPropertyDescriptors(sourse));console.log(tar);//console.log(Object.getOwnPropertyDescriptor(tar,'foo'));

实现浅拷贝
var obj = {a: 1, b: 2, c: 3};const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));/*Object.getPrototypeOf(obj)得到obj的原型*Object.getOwnPropertyDescriptors(obj)获取obj上面所有属性,克隆obj上面的属性 */console.log(clone);//{a: 1, b: 2, c: 3}
封装
var obj = {a: 1, b: 2, c: 3};// const clone = Object.create(Object.getPrototypeOf(obj), Object.getOwnPropertyDescriptors(obj));/*Object.getPrototypeOf(obj)得到obj的原型*Object.getOwnPropertyDescriptors(obj)获取obj上面所有属性,克隆obj上面的属性 */const clone = (obj) => Object.create(Object.getPrototypeOf(obj),Object.getOwnPropertyDescriptors(obj))// console.log(clone);//{a: 1, b: 2, c: 3}console.log(clone(obj));//{a: 1, b: 2, c: 3}
这是新增api,但不讲不行,用的相对少一点,但解决方案是唯一的
部署对象
1. const obj = {a:1}2. const obj = Object.create(prototype);obj.foo = 123;3. const obj = Object.assign(Object.create(prototype),{foo:123});4. const obj = Object.create(prototype,Object.getOwnPropertyDescriptors({foo:123}));
