对象两种定义形式javascript
声明(文字)形式前端
构造形式java
//声明(文字)形式 var myObj = { key: value // ... } //构造形式 var myObj = new Object(); myObj.key = value;
对象是 JavaScript 的基础。在 JavaScript 中一共有六种主要类型(术语语言类型
)算法
string编程
number数组
boolean安全
null微信
undefined编程语言
object函数
注意,简单基本类型(string,number,boolean,undefined,null)自己并非对象。
null 有时会被当作对象类型,但这其实只是语言自己的一个 bug,即对 null 执行 typeof null 时会返回"object" 。实际上,null 自己是基本类型。
函数式对象的一个子类型,JavaScript 中的函数是“一等公民”
JavaScript 中还有一些对象子类型,一般被称为内置对象。有些内置对象的名字看起来和简单基础类型同样,不过实际上它们的关系更复杂,
String
Number
Boolean
Object
Function
Array
Date
RegExp
Error
这些内置函数能够当作构造函数(由 new 产生的函数调用)来使用,从而能够构造一个对应子类型的新对象。举例来讲:
var strPrimitive = "I am string"; //文字形式定义 typeof(strPrimitive); // "string" strPrimitive instanceof String; // false var strObject = new String("I am string");//构造形式定义 typeof(strObject); //"object" strObject instanceof String; //true //检查 sub-type 对象 Object.prototype.toString.call(strObject);//[object String]
Object.prototype.toString...咱们能够认为子类型在内部借用了 Object 中的 toString()方法。
因为 javascript 弱类型的编程语言,原始值 "I am string"在必要的时候回自动把字符串字面量转换成一个 String 对象。
思考下面代码:
var strPrimitive = "I am a string"; console.log(strPrimitive.length); //13 console.log(strPrimitive.charAt(3));//m
使用以上两种方法,咱们均可以直接在字符串字面量上访问属性和方法,之因此能够这么作,是由于引擎自动把字面量转换成 String 对象,因此能够访问属性和方法。
null 和 undefined 没有对应的构造形式,他们只有文字形式。相反,Date 只有构造,没有文字形式。
对象的内容是由一些存储在特定命名位置的(任意类型的)值组成的,咱们称之为属性。
var myObject = { a:2, 'a_arr':3 } myObject.a; //2 属性访问 myObject["a"]; //2 键访问 myObject["a_arr"]; //3
.操做符
要求属性命名知足标识符的命名规范,而["..."]语法能够接受任意 UTF-8/Unicode 字符串为属性名
在对象中,属性名永远都是字符串。若是你使用 string(字面量)之外的其余值做为属性名,那它首先会被转换为一个字符串。即便是数字也不例外,虽然在数组下标中使用的的确是数字,可是在对象属性名中数字会被转换成字符串,因此小心不要搞混对象和数字的用法。
var myObject = {} myObject[true] = "foo"; myObject[3] = "bar"; myObject[myObject] = "baz"; myObject["true"]; //"foo" myObject["3"]; //"bar" myObject["[object Object]"]; //"baz"
ES6
增长了可计算属性名,能够再文字形式中使用[]包裹一个表达式来当作属性名:
var prefix = "foo"; var myObject = { [prefix + "bar"]:"hello", [prefix + "baz"]:"world", }; myObject["foobar"]; //hello myObject["foobaz"]; //world
可计算属性名最经常使用的场景多是 ES6的符号(Symbol)
它是一种新的基础数据类型,包含一个不透明且没法预测的值
数组也支持[]访问形式,数组期房的是数值下标,也就是说值存储的位置(索引)是整数。
var arr =[1,"a",2]; arr.length; //3 arr[0]; //1 arr[1]; //"a" arr.x = "x"; arr.length; //3 arr.x; //"x" arr["3"] = 3; arr.length; //4 arr[3]; //3
数组也是对象,因此虽然每一个下标都是整数,你仍然能够给数组添加属性
注意: 若是你试图向数组添加一个属性,当时属性名“看起来”想一个数字,那他会编程一个数值下标(所以会修改数组的内容而不是添加一个属性)
javascript 初学者最多见的问题之一就是如何复制一个对象。实际上咱们没法选择默认一个复制算法。
举例来讲,思考一下这个对象:
function anotherFunction(){/**/} var anohterObject = { c: true }; var anotherArray = []; var myObject = { a: 2, b: anotherObject,//引用,不是副本 c: anotherArray,//另外一个引用 d: anotherFunction }; anotherArray.push( anotherObject, myObject);
对象复制时,咱们应该判断它是浅复制仍是深复制。
对于浅拷贝来讲,复制出的新对象中 a 的值会复制旧对象中 b、c、d 引用的对象是同样的。
对于深拷贝来讲,除了复制 myObject 之外还会复制 anotherObject 和 anotherArray。这时问题就来了,anotherArray 引用了 anotherObject 和 myObject,因此又须要复制 myObject,这样就会因为循环引用致使死循环。
有一巧妙的复制方法:
var newObj = JSON.parse(JSON.stringify( someObj ));
这种方法须要保证对象是 Json 安全的的,因此只适用于部分状况。
相对于深复制,浅复制就很是易懂而且问题要少得多,因此 ES6定义了 Object.assign(...)
方法来实现浅复制。
Object.assign() :第一个参数是目标对象,以后能够跟一个或多个源对象。
它会遍历一个或多个源对象的全部可枚举的自由键并把他们复制到目标对象,最后返回目标对象。
var obj = Object.assign({},myObject); obj.a; //2 obj.b === anotherObject;//true obj.c === anotherArray;//true obj.d === anotherFunction;//true
在 ES5
以前,JavaScript 语言自己并无提供能够直接检测属性特性的方法,好比判断属性是否可读。
可是从 ES5开始,全部的属性都具有了属性描述符
。
思考下面代码:
var myObject = { a:2 }; Object.getOwnPropertyDescriptor( myObject,"a" ); // { // value:2, // writable:true, // enumerable:true, // configurable:true // }
能够经过 Object.defineProperty(...) 添加或者修改一个已有属性
Vue 的双向绑定的基础就是基于这个函数,重写 get set 方法,在使用发布-订阅模式来完成数据的动态更新
详情能够看Vue 动态数据绑定(一)和Vue 动态数据绑定三大难点
configurable:false 时:
它将不能再使用Object.defineProperty(...)进行配置
可是能够将 writable的状态由 true->false(没法 false->true)
delete 无效
对象常量
结合 writable:false 和 configurable:false
var myObject ={}; Object.defineProperty( myObject, "NUMBER",{ value:42, writable:false, configurable:false });
禁止扩展
若是你想禁止一个对象添加新属性而且保存已有属性,可使用 Object.preventExtensions(...)
var myObject ={ a:2 } Object.preventExtensions(myObject); myObject.b =3; myObject.b; //undefined
在费严格模式下,建立属性 b 会静默失败。在严格模式下,将会抛出 TypeError 错误。
密封
Object.seal(...)会建立一个"密封"的对象,这个访问实际上会在一个现有对象上调用 Object.preventExtensions(...)并把全部现有属性标记为configurable:false。
密封后,不能添加新属性,也不能从新配置或删除任何现有属性(能够修改属性的值)
冻结
Object.freeze(...)会建立一个冻结对象,这个方法实际上会在一个现有对象调用 Object.seal(...)并把全部“数据访问”属性 wirtable:false,这样就没法修改他们的值了
更多内容能够订阅本人微信公众号,一块儿开启前端小白进阶的世界!