企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
[TOC] **** ## 0 意义 Object(对象)是js中内置对象之一。可以将对象看成键值数据结构。 键值对中的键称为对象的属性只能是数字或者字符串 键值对中的值可以是任意其他类型 除了null和undefined,其他所有的都可以转换为对象 ## 1 简单例子 ### 1-2 对象的引用使用 ~~~ var studenA = { name:"sundway" } var studentB = studentA; studentB.name = "modify"; console.log(studentA.name); //"modify" console.log(studentB.name); //"modify" //studentA和studentB同时是对内存中的一个引用。修改其中的一个值会影响另一个 ~~~ ### 1-2 对象的属性只能是字符串或者数字 ~~~ var studentA = { "name" : "sundway" } var studentA = { 1 : "sundway } console.log(studentA[1]); //输出"sundway" //属性为数字时,不能使用.运算符读取属性值,只可以使用[]读取属性值 ~~~ ### 1-3 除了null和undefined转换到对象 ~~~ 2.toString(); // Uncaught SyntaxError 2..toString(); // the second point is correctly recognized 2 .toString(); // note the space left to the dot (2).toString(); // 2 is evaluated first ~~~ ## 2 对象属性 ### 2-1 属性描述 属性描述符:包含数据描述符和存储描述符 数据描述符(configurable,enumerable,value,writable) 数据描述符实现对数据可写或不可写值的属性信息描述 存取描述符(configurable,enumerable,get,set) 存储描述符由一对getter-setter函数来描述属性 描述符鄙视两种形式之一,不能同时是两者 ### 2-2 Object.prototype 对象的原型对象属性, 所有对象都是基于Object,通过指定Object.prototype为特定对象 可以实现对象对其他对象的属性和方法继承,也可以被覆盖 ### 2-3 Object.prototype.constructor 指向创建该对象原型的函数引用 属性的值是一个函数本身。 ### 2-4 Object.prototype.__proto__ 对象的proto属性和自己内部的Protototype指向相同的值 原型的值可以是一个对象也可以是Null。 使用Object.getPrototypeOf获取对象的原型 ## 3 对象方法 ### 3-1 Object.create() 创建一个新的对象 ~~~ ;模拟实现 if(typeof Object.create != 'function'){ Object.create = (function(){ //为了节省内存,使用一个共享的构造器 function Temp() {}; // 使用 Object.prototype.hasOwnProperty 更安全的引用 var hasOwn = Object.prototype.hasOwnProperty; return function (O) { // 1. 如果 O 不是 Object 或 null,抛出一个 TypeError 异常。 if (typeof O != 'object') { throw TypeError('Object prototype may only be an Object or null'); } // 2. 使创建的一个新的对象为 obj ,就和通过 // new Object() 表达式创建一个新对象一样, // Object是标准内置的构造器名 // 3. 设置 obj 的内部属性 [[Prototype]] 为 O。 Temp.prototype = O; var obj = new Temp(); // 不要保持一个 O 的杂散引用(a stray reference)... Temp.prototype = null; // 4. 如果存在参数 Properties ,而不是 undefined , // 那么就把参数的自身属性添加到 obj 上,就像调用 // 携带obj ,Properties两个参数的标准内置函数 // Object.defineProperties() 一样。 if (arguments.length > 1) { // Object.defineProperties does ToObject on its first argument. var Properties = Object(arguments[1]); for (var prop in Properties) { if (hasOwn.call(Properties, prop)) { obj[prop] = Properties[prop]; } } } // 5. 返回 obj return obj; }; })() } ~~~ ### 3-2 Object.is() 判断两个值是否同一个值 ~~~ ;基于===模拟实现 Object.is = function(x, y) { // SameValue algorithm if (x === y) { // Steps 1-5, 7-10 // Steps 6.b-6.e: +0 != -0 return x !== 0 || 1 / x === 1 / y; } else { // Step 6.a: NaN == NaN return x !== x && y !== y; } }; ~~~ ### 3-3 Object.assign(target,...sources) 拷贝源对象到目标对象,返回目标对象 ~~~ ;模拟实现 if (!Object.assign) { Object.defineProperty(Object, "assign", { enumerable: false, configurable: true, writable: true, value: function(target, firstSource) { "use strict"; if (target === undefined || target === null) throw new TypeError("Cannot convert first argument to object"); var to = Object(target); for (var i = 1; i < arguments.length; i++) { var nextSource = arguments[i]; if (nextSource === undefined || nextSource === null) continue; var keysArray = Object.keys(Object(nextSource)); for (var nextIndex = 0, len = keysArray.length; nextIndex < len; nextIndex++) { var nextKey = keysArray[nextIndex]; var desc = Object.getOwnPropertyDescriptor(nextSource, nextKey); if (desc !== undefined && desc.enumerable) to[nextKey] = nextSource[nextKey]; } } return to; } }); } ~~~ ~~~ ;Demo 拷贝symbol类型的属性 var o1 = { a: 1 }; var o2 = { [Symbol("foo")]: 2 }; var obj = Object.assign({}, o1, o2); console.log(obj); // Object {a: 1, Symbol(foo): 2} ;继承属性和不可枚举属性是不能拷贝的 var obj = Object.create({foo: 1}, { // foo 是个继承属性。 bar: { value: 2 // bar 是个不可枚举属性。 }, baz: { value: 3, enumerable: true } }); var copy = Object.assign({}, obj); console.log(copy); // Object {baz: 3} ;原始值会被隐式转换为其他包装对象 var v1 = "123"; var v2 = true; var v3 = 10; var v4 = Symbol("foo") var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // 源对象如果是原始值,会被自动转换成它们的包装对象, // 而 null 和 undefined 这两种原始值会被完全忽略。 // 注意,只有字符串的包装对象才有可能有自身可枚举属性。 console.log(obj); // { "0": "1", "1": "2", "2": "3" } ;拷贝过程中发生异常 var target = Object.defineProperty({}, "foo", { value: 1, writeable: false }); // target 的 foo 属性是个只读属性。 Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4}); // TypeError: "foo" is read-only // 注意这个异常是在拷贝第二个源对象的第二个属性时发生的。 console.log(target.bar); // 2,说明第一个源对象拷贝成功了。 console.log(target.foo2); // 3,说明第二个源对象的第一个属性也拷贝成功了。 console.log(target.foo); // 1,只读属性不能被覆盖,所以第二个源对象的第二个属性拷贝失败了。 console.log(target.foo3); // undefined,异常之后 assign 方法就退出了,第三个属性是不会被拷贝到的。 console.log(target.baz); // undefined,第三个源对象更是不会被拷贝到的。 ~~~ ### 3-4 Object.keys(obj) 返回对象的可枚举自身属性的属性名组成的数组 ### 3-5 Object.defineProperty(obj,prop,descriptor) 直接在对象上定义一个新属性,并返回这个对象 ### 3-6 Object.defineProperties(obj,props) 在一个对象上添加或修改一个或者多个自由属性,并返回这个对象 ### 3-7 Object.freeze(obj) 冻结一个对象。这个对象不可改变 ### 3-8 Object.isFrozen(obj) 判断一个对象是否被冻结 ### 3-9 Object.preventExtensions(obj) 禁止一个对象可扩展,永远不可能对对象添加新的属性 ### 3-10 Object.isExtensible(obj) ## 4 资源 [js中的object](https://segmentfault.com/a/1190000004224842)