Undefined、Null、Boolean、Number、String
Object、Array、Function等
基本数据类型存放在栈中。存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配,是直接按值存放的,所以可以直接访问。引用类型存放在堆中。引用类型(object)是存放在堆内存中的,变量实际上是一个存放在栈内存的指针,这个指针指向堆内存中的地址。每个空间大小不一样,要根据情况开进行特定的分配。
var person1 = {name:'jozo'}; var person2 = {name:'xiaom'}; var person3 = {name:'xiaoq'};
let a = {"name": "jack"}; let b = {"name": "jack"}; //比较运算符 console.log(a == b) // false console.log(a === b) // false
1.利用JSON.stringify()
let a = {"name": "jack"}; let b = {"name": "jack"}; JSON.stringify(a) === JSON.stringify(b); // true a = {"name": "jack", "age":"18"}; b = {"age":"18", "name": "jack"}; JSON.stringify(a) === JSON.stringify(b); // false
缺点:Object属性顺序需要完全一致
2.利用_.isEqual()
_.isEqual(value, other)
参数:value比较的值,other拿来比较的值
返回值:(boolean)是否相等
// lodash Method _.isEqual(a,b); //true
直接设置key/value
let obj = {}; obj.name = "jack"; // obj: {name: "jack"} obj['name'] = "jack"; // obj: {name: "jack"}
Object.assign(target, …sources)
参数:target(目标对象), sources(源对象)
返回值: 目标对象
如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖。后来的源的属性将类似地覆盖早先的属性。Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。
obj1增加’b’属性
var obj1 = {a:1}; var obj2 = {b:2}; var obj = Object.assign(obj1, obj2); // {a: 1, b: 2} obj1 // {a: 1, b: 2}, 注意目标对象自身也会改变。 obj2 // {b:2}; Object.assign(obj1, {b: 3}); // {a: 1, b: 3}
如果不想更改原对象,可以
var obj = {a: 1}; var copy = Object.assign({}, obj, {b:2}); console.log(copy); // {a: 1, b: 2}
_.assignIn(object, [sources])
与.assign类似,只不过.assignIn()不仅遍历了自身,还有遗传的属性
function Foo() { this.a = 1; } function Bar() { this.c = 3; } Foo.prototype.b = 2; Bar.prototype.d = 4; _.assignIn({ 'a': 0 }, new Foo, new Bar); // => { 'a': 1, 'b': 2, 'c': 3, 'd': 4 }
es6解构
let obj1 = {a: 1, b: 2}; obj1 = {...obj1, c: 3}; // {a: 1, b: 2, c: 3} let obj2 = {c: 2, d: 2}; obj1 = {...obj1, ...obj2}; // {a: 1, b: 2, c: 2, d: 2}
_.clone(value)
创建一个value的浅拷贝对象
var person = { name: 'jack', shcool: { grade: 7, class: 10 } }; var shallow = _.clone(person); // {name: 'jack', school: {grade: 7, class: 10}} console.log(person.school === shallow.school) // true
_.cloneDeep(value)
与_.clone()类似,只不过这个方法递归地克隆属性(深拷贝)
var person = { name: 'jack', shcool: { grade: 7, class: 10 } }; var deep = _.cloneDeep(person); // {name: 'jack', school: {grade: 7, class: 10}} console.log(person.school === deep.school) // false
深拷贝和浅拷贝
基本类型存放在栈中,基本类型的比较是值的比较。
应用类型存放在堆中,应用类型的比较是引用的比较。
var obj1 = { 'name' : 'zhangsan', 'age' : '18', 'language' : [1,[2,3],[4,5]], }; var obj2 = obj1; // 赋值操作 var obj3 = _.clone(obj1); // 浅拷贝 obj2.name = "lisi"; obj3.age = "20"; obj2.language[1] = ["二","三"]; obj3.language[2] = ["四","五"]; console.log(obj1); //obj1 = { // 'name' : 'lisi', // 'age' : '18', // 'language' : [1,["二","三"],["四","五"]], //}; console.log(obj2); //obj2 = { // 'name' : 'lisi', // 'age' : '18', // 'language' : [1,["二","三"],["四","五"]], //}; console.log(obj3); //obj3 = { // 'name' : 'zhangsan', // 'age' : '20', // 'language' : [1,["二","三"],["四","五"]], //};
改变 obj2 的 name 属性和 obj3 的 name 属性,可以看到,改变赋值得到的对象 obj2 同时也会改变原始值 obj1,而改变浅拷贝得到的的 obj3 则不会改变原始对象 obj1。但此时改变赋值得到的对象 obj2 和浅拷贝得到的 obj3 中的 language 属性的第二个值和第三个值(language 是一个数组,也就是引用类型)。结果见输出,可以看出来,无论是修改赋值得到的对象 obj2 和浅拷贝得到的 obj3 都会改变原始数据。
这是因为浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。所以就会出现改变浅拷贝得到的 obj3 中的引用类型时,会使原始数据得到改变。
深拷贝:将 B 对象拷贝到 A 对象中,包括 B 里面的子对象,
浅拷贝:将 B 对象拷贝到 A 对象中,但不包括 B 里面的子对象
– | 和原数据是否指向同一对象 | 第一层数据为基本数据类型 | 原数据中包含子对象 |
---|---|---|---|
赋值 | 是 | 改变会使原数据一同改变 | 改变会使原数据一同改变 |
浅拷贝 | 否 | 改变不会使原数据一同改变 | 改变会使原数据一同改变 |
深拷贝 | 否 | 改变不会使原数据一同改变 | 改变不会使原数据一同改变 |
使用delete
let obj = { "a": 1, "b": 2, "c": 3 } delete obj.a; console.log(obj); // {b: 2, c: 3} delete obj['c']; console.log(obj); // {b: 2}
优点:最常用有效的办法
缺点:性能较差,不建议在规模较大的循环中使用
undefined
let obj = { "a": 1, "b": 2, "c": 3 } obj.a = undefined; console.log(obj); // {a: undefined, b: 2, c: 3}
性能较好,但是键值仍会存在Object中,可在有些需要的情况下使用。
_.omit(object, [paths])
参数:object (Object) 源对象, [paths] ( …(string|string[]) ) 删除的属性名
返回值:新对象
let object = {'a': 1, 'b': '2', 'c': 3 , 'd': 4}; _.omit(object, 'a'); // {b: "2", c: 3, d: 4},注意源对象不变 _.omit(object, ['a', 'c']); // {b: "2", d: 4}
_.unset(object, path)
参数:object (Object) 修改的对象,path (Array|string) 属性的路径
返回值:(boolean)返回属性是否删除成功
var object = { 'a': { 'b': { 'c': 3 } } }; _.unset(object, 'a.b.c'); // true console.log(object); // {a: b: {}} _.unset(object, ['a', 'b', 'c']); // true console.log(object); // {a: b: {}}
es6
let obj = {a: 1, b: 2, c: 3}; let { a, ...newObj } = obj; console.log(newObj); // {b: 2, c: 3}
根据key值
一般来说,访问对象属性使用的都是点表示法,不过在JavaScript中也可以使用方括号表示法来访问对象的属性,在使用方括号语法时,应该将要访问的属性以字符串的形式放在方括号中。
et person = { "name": "jack", "age": 29 } console.log(person.name); // 'jack' console.log(person["age"]); // 29
注意:当用变量来访问属性时,必须使用方括号表示法
let pname = "name"; let person = { "name": "jack", "age": 29 } console.log(person.pname); // undefined console.log(person[pname]); // 'jack'
通常,除非必须使用变量来访问属性,否则建议使用点表示法。
参数:collection (Array|Object)目标对象,[predicate=_.identity] (Function)判断函数,[fromIndex=0] (number)开始序号
返回值:返回第一个匹配的元素,否则为undefined。
let user = { "jack": { "sex": "male", "age": 25, "city": "ShenZhen" }, "mike": { "sex": "male", "age": 22, "city": "GuangZhou" }, "mary": { "sex": "female", "age": 19, "city": "HangZhou" } } _.find(user, (o) => o.age>18); // 返回jack的value _.find(user, {'sex': 'female', 'age': 19}); // 返回mary的value _.find(user, {'sex': 'male'}, 1); // 返回mike的value
数组也同样适用
let users = [ { 'user': 'barney', 'age': 36, 'active': true }, { 'user': 'fred', 'age': 40, 'active': false }, { 'user': 'pebbles', 'age': 1, 'active': true } ]; _.find(users, function(o) { return o.age < 40; }); // => object for 'barney' _.find(users, { 'age': 1, 'active': true }); // => object for 'pebbles' _.find(users, ['active', false]); // => object for 'fred' _.find(users, 'active'); // => object for 'barney'
.findLast()与.find()类似,只不过从右向左查找。
参数:object (Object)源对象,[paths] (…(string|string[]))要提取的属性名。
返回值:返回一个新的Object
var object = { 'a': 1, 'b': '2', 'c': 3 }; _.pick(object, ['a', 'c']); // => { 'a': 1, 'c': 3 }
参数:object (Object)源对象,[predicate=_.identity] (Function)判断函数。
返回值: 返回一个新Object
let object = {'a': 1, 'b': '2', 'c': 3}; _.pickBy(object, _.isNumber); // {'a': 1, 'c': 3} let user = { "jack": { "sex": "male", "age": 25, "city": "ShenZhen" }, "mike": { "sex": "male", "age": 22, "city": "GuangZhou" }, "mary": { "sex": "female", "age": 19, "city": "HangZhou" } } _.pickBy(user, (o) => o.age>19); // {"jack": {...}, "mike": {...}} _.pickBy(user, {"age": 25}); // {"jack": {sex: "male", age: 25, city: "ShenZhen"}}
点表示法、中括号表示法
var object = { 'a': { 'b': { 'c': 3 } } }; object.a.b.c = 4; // {a :{b: {c: 4}}} object['a']['b']['c'] = 5; // {a :{b: {c: 5}}}
和上面查的方法一致
_.set(object, path, value)
参数:object (Object) 更改的对象,path (Array|string) 属性的路径,value (*):需要设置的值
返回值:(Object)返回对象
var object = { 'a': { 'b': { 'c': 3 } } }; _.set(object, 'a.b.c', 4); console.log(object.a.b.c); // 4 _.set(object, '["a"]["b"]["c"]', 5); console.log(object.a.b.c); // 5 _.set(object, ['a', 'b', 'c'], 6); console.log(object.a.b.c); // 6
_.update(object, path, updater)
参数:object (Object) 修改对象,path (Array|string) 属性路径,updater (Function) 产生更新值的函数。
返回值:(Object) 返回对象
var object = { 'a': { 'b': { 'c': 3 } } }; _.update(object, 'a.b.c', function(n) { return n * n; }); console.log(object.a.b.c); // 25 _.update(object, 'x.y.z', function(n) { return n ? n + 1 : 0; }); console.log(object.x.y.z); // 0
原文链接https://jhanlu.github.io/2017/12/13/Object%E5%AF%B9%E8%B1%A1%E5%B8%B8%E7%94%A8%E6%93%8D%E4%BD%9C/
伍仔 2016-12-03
寒江独钓 2018-05-16
泡泡 2018-07-13
泡泡 2017-01-28
泡泡 2016-07-15
伍仔 2017-07-24
碧浪晴空 2023-05-05
小海 2019-11-26
荡神戏魔 2018-09-18
jacket139 2021-12-20
藏家320 2025-03-29
藏家632 2025-03-29
木木 2025-03-29
藏家259 2025-03-29
藏家259 2025-03-29
藏家999 2025-03-29
藏家929 2025-03-29
Henry 2025-03-29
藏家869 2025-03-29
藏家181 2025-03-29