var a={"id":1,"name":"danlis"};
//添加属性
a.age=18;
console.log(a);
//结果:Object { id: 1, name: "danlis", age: 18 }
//修改属性
a.age="我怎么知道";
//结果:Object { id: 1, name: "danlis", age: "我怎么知道" }
//删除属性
delete a.age;
//结果:Object { id: 1, name: "danlis" }
转载地址:https://www.cnblogs.com/donghuang/archive/2017/11/01/7765761.html
平时在写的代码过程中,经常会遇到对对象Object的数据处理。而在对对象的数据处理中,操作最频繁的是“数据引用”、“值的修改”、“获取关键字(属性)”。平时最烦的也是“获取关键字”,经常忘记怎么去获取,这里做一下整理。
既然要"获取关键字",那么得首先有一个对象才行。创建对象的方式很多,我自己惯用的方式有三种:
1、通过原始构造函数 new Object();创建一个对象,然后赋值;
var testObj= new Object(); testObj.name = "shangguan"; testObj.age= 25; testObj.action = function () { return this.name; }2、直接新建对象,不通过构造函数(而且直接新建速度比构造器还快一些!)
var testObj={}; testObj.name = "shangguan"; testObj.age= 25; testObj.action = function () { return this.name; };3、重载构造器,让构造器在构造对象时按预定的属性构建。
// 创建一个对象的构造方法 function newObj(name, age) { this.name = name; this.age= age; this.action = function () { return this.name; } } // 创建一个对象 var testObj= new newObj("shangguan", 25);
1、对象内置属性方法:Object.keys();该方法返回一个数组,数组内包括对象内可枚举属性以及方法名称。数组中属性名的排列顺序和使用
for...in
遍历该对象时返回的顺序一致。// 通过调用Object.keys()方法,获取对象上已定义(可枚举)的属性和方法
var keys= Object.keys(testObj); console.log(keys); // 输出 keys ["name", "age", "action"]
![]()
注意:在ES5里,如果此方法的参数不是对象(而是一个原始值),那么它会抛出 TypeError。而在ES2015中,非对象的参数将被强制转换为一个对象。
Object.keys("testObj"); // TypeError: "testObj" is not an object (ES5 code) Object.keys("testObj"); //["name", "age", "action"] (ES2015 code)2、
Object.getOwnPropertyNames():
方法返回一个指定对象所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。该数组是
obj
自身拥有的枚举或不可枚举属性名称字符串集合。 数组中枚举属性的顺序与通过for...in
循环(或Object.keys()
)迭代该对象属性时一致。数组中不可枚举属性的顺序未定义。var keys = Object.getOwnPropertyNames(testObj); console.log(keys); // 输出 keys ["name", "age", "action"]
3、当然除了以上两个外,还有最原始的 for...in 循环(估计是平时循环用的多了,反倒是这个不怎么用!)
var keys =[]; for(var i in testObj){ keys.push(i); } console.log(keys); // keys ["name", "age", "action"]
下面通过一个实例,直观说明三者之间的区别:
var testObj = Object.create({}, { getFoo: { value: function () { return this.foo; }, enumerable: false } }); testObj.name = "shangguan"; testObj.age = 25; testObj.action = function(){ return this.name; }; function getKeys() { // 获取对象可枚举和不可枚举的属性 console.log(Object.getOwnPropertyNames(testObj)); //输出:["getFoo", "name", "age", "action"] // 获取对象可枚举的属性 console.log(Object.keys(testObj)); //输出:["name", "age", "action"] // 获取对象可枚举的属性 for (var i in testObj) { console.log(i); //输出 name,age,action } //返回直接定义在该对象上的可枚举属性,非继承。通过hasOwnProperty()方法可以将那些属性是对象自身(非继承)属性筛选出来,从而将不可枚举属性排除出去 //obj.hasOwnProperty(prop): prop要检测的属性,字符串 名称或者 Symbol。 返回值:用来判断某个对象是否含有指定的属性 的Boolean值 for (var i in testObj) { if(testObj.hasOwnProperty(i)) { console.log(i); } //输出 name,age,action } }
总结:如果只需要获取可枚举属性,那么
Object.keys()
或for...in
循环迭代即可(Object.getOwnPropertyNames()也可以获取到原型链上的可枚举属性,不过需要通过hasOwnProperty()
方法过滤掉不可枚举属性)。
var a={"id":1,"name":"xiaocai"}; //添加属性 a.age=18; console.log(a); //结果:Object { id: 1, name: "xiaocai", age: 18 } //修改属性 a.age="你猜"; console.log(a); //结果:Object { id: 1, name: "xiaocai", age: "我怎么知道" } delete a.age; console.log(a); //结果:Object { id: 1, name: "xiaocai" }
总结:删除对象属性使用delete就可以了,删除哪个就delete哪个
var a={"id":1,"name":"danlis"}; //添加属性 a.age=18; console.log(a); //结果:Object { id: 1, name: "danlis", age: 18 } //修改属性 a.age="我怎么知道"; //结果:Object { id: 1, name: "danlis", age: "我怎么知道" } //删除属性 delete a.age; //结果:Object { id: 1, name: "danlis" }
转载于:https://www.cnblogs.com/guoliping/p/9957141.html
浅比较
概念:浅比较也称引用相等,在js中===是做浅比较,只检查左右两边是否是同一个对象的引用;{a:1} === {a:1} // false const m = {a:1}; const n = {a:1}; m === n //false const m = {a:1}; const n = m; m === n //true const m = {a:1}; m === {a:1} //false; changeValue(params) { params.a = 2; return params; } const m = {a:1}; const n = changeValue(m); m === n //true m //{a:2} n //{a:2} ps: 这里`changeValue`方法直接修改了传入的参数`params`,这么做造成的后果是把 `m`的值也改变了 (因为javascript中,基本类型是传值调用,引用类型是传引用调用) 所以这种做法在`webstrom`中也会有警告,尽量不要这么做;
如果不同的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址。修改其中一个变量,会影响到其他所有变量。
这种引用只局限于对象,如果两个变量指向同一个
原始类型的值
。那么,变量这时都是值的拷贝。1 === 1 //true const m = 1; const n = 1; m === n //true const m = 1; const n = m; m === n //true changeValue(params) { params = params + 1; return params; } const m = 1; const n = changeValue(m); m === n //false m //1 n //2
深比较
深比较也称原值相等,深比较是指检查两个对象的所有属性是否都相等,深比较需要以递归的方式遍历两个对象的所有属性,操作比较耗时,深比较不管这两个对象是不是同一对象的引用。
javascript没有提供深比较的api,需要自己实现,网上有很多,具体查一下吧实现深比较:首先实现个深拷贝
思路:
1、传递进来的是函数时,不需要操作,直接返回即可
因外执行环境栈中一个名字的函数只能有一个,如果我们自己在克隆一个会把原来的替换掉,这样做没有任何意思;
2,传递的参数是基本的数据类型,不操作直接返回;
3,传递的是对象类型时
(1).正则对象:创建一个新实列存储当前正则返回即可(因为我们的目的是让当前的地址不一样即可)
(2).日期对象创建一个日期实列存储当前日期,
(3)普通对象,创建一个新的实列,循环存储当前的信息;function _cloneDeep(obj) { // 传递进来的如果不是对象,则无需处理,直接返回原始的值即可(一般Symbol和Function也不会进行处理的) if (obj === null) return null; if (typeof obj !== "object") return obj; // 过滤掉特殊的对象(正则对象或者日期对象):直接使用原始值创建当前类的一个新的实例即可,这样克隆后的是新的实例,但是值和之前一样 if (obj instanceof RegExp) return new RegExp(obj); if (obj instanceof Date) return new Date(obj); // 如果传递的是数组或者对象,我们需要创建一个新的数组或者对象,用来存储原始的数据 // obj.constructor 获取当前值的构造器(Array/Object) let cloneObj = new obj.constructor; for (let key in obj) { // 循环原始数据中的每一项,把每一项赋值给新的对象 if (!obj.hasOwnProperty(key)) break; cloneObj[key] = _cloneDeep(obj[key]); } return cloneObj; }
2、深比较实现
语法:let res = _assignDeep(obj1,obj2)思路:
1.首先克隆一份obj1 2.循环拿obj2中的每一项与克隆的obj1比较 如果当前拿出这一项是对象数据类型 并且 克隆的obj1 中相同属性名对应的也是对象数据类型的值, 再次进行深比较,用递归处理一下即可; 其余情况都直接用obj2的值替换obj1的值即可; function _assignDeep(obj1, obj2) { // 先把OBJ1中的每一项深度克隆一份赋值给新的对象 let obj = _cloneDeep(obj1); // 再拿OBJ2替换OBJ中的每一项 for (let key in obj2) { if (!obj2.hasOwnProperty(key)) break; let v2 = obj2[key], v1 = obj[key]; // 如果OBJ2遍历的当前项是个对象,并且对应的OBJ这项也是一个对象,此时不能直接替换,需要把两个对象重新合并一下,合并后的最新结果赋值给新对象中的这一项 if (typeof v1 === "object" && typeof v2 === "object") { obj[key] = _assignDeep(v1, v2); continue; } obj[key] = v2; } return obj; }