资讯专栏INFORMATION COLUMN

笔记-你不知道的JS-对象

senntyou / 1438人阅读

摘要:内置对象,在中,它们实际上只是一些内置函数。这些内置函数可以当作构造函数,使用调用,产生新对象。在必要时语言会自动把字符串字面量转换成一个对象,也就是说你并不需要显式创建一个对象。属性操作符要求属性名满足标识符的命名规范。

1 如何定义
// 声明形式,大部分情况下使用声明形式
let obj ={
  a:2,
  b:3
};
// 构造形式
let obj= = new Object();
obj.a=2;
obj.b=3;
2 类型

7种类型:string、boolean、number、null 、 undefined、object、symbol

typeof null === object,原理是这样的,不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。

内置对象:String, Number, Object, Date, Boolean, Array, Function, RegExp, Error,在 JavaScript 中,它们实际上只是一些内置函数。这些内置函数可以当作构造函数,使用 new 调用,产生新对象。

在必要时语言会自动把字符串字面量转换成一个 String 对象,也就是说你并不需要显式创建一个对象。

var strPrimitive = "I am a string"; 
console.log( strPrimitive.length ); // 13 
console.log( strPrimitive.charAt( 3 ) ); // "m"

我们都可以直接在字符串字面量上访问属性或者方法,之所以可以这样做,是因为引擎自动把字面量转换成 String 对象,所以可以访问属性和方法。同样引擎会自动把数字字面量转换为Number对象,如使用3.1415.toFixed(2)

null 和 undefined 没有对应的构造形式,它们只有文字形式。相反,Date 只有构造,没有文字形式。
对于 Object、Array、Function 和 RegExp(正则表达式)来说,无论使用文字形式还是构造形式,它们都是对象,不是字面量。

Error 对象很少在代码中显式创建,一般是在抛出异常时被自动创建。也可以使用 newError(..) 这种构造形式来创建。

3 属性

. 操作符要求属性名满足标识符的命名规范。

在对象中,属性名永远都是字符串。如果你使用 string(字面量)以外的其他值作为属性名,那它首先会被转换为一个字符串。

var myObject = { };
let arr = [2,3];
myObject[true] = "foo"; 
myObject[3] = "bar"; 
myObject[myObject] = "baz";
myObject[arr] =4;
myObject["true"]; // "foo"
myObject["3"]; // "bar"
myObject["[object Object]"]; // “baz”
myObject["2,3"]; // 4

为数组添加命名属性,但数组的length值不会变

4 复制

对于 JSON 安全(也就是说可以被序列化为一个 JSON 字符串并且可以根据这个字符串解析出一个结构和值完全一样的对象)的对象来说,有一种巧妙的复制方法:

var newObj = JSON.parse( JSON.stringify( someObj ) );
Object.assign(..) 方法的第一个参数是目标对象,之后还可以跟一个或多个源对象。它会遍历一个或多个源对象的所有可枚举(enumerable,参见下面的代码)的自有键(owned key,很快会介绍)并把它们复制(使用 = 操作符赋值)到目标对象,最后返回目标对象。

5 属性描述符
var myObject = { a:2};
Object.getOwnPropertyDescriptor( myObject, "a" );
// {
// value: 2,
// writable: true,
// enumerable: true,
// configurable: true 
// }
// writable(可写)、 enumerable(可枚举)和 configurable(可配置)

不管是不是处于严格模式,尝试修改一个不可配置的属性描述符都会出错,也不可以删除该属性。注意:如你所见,把 configurable 修改成false 是单向操作,无法撤销!要注意有一个小小的例外:即便属性是 configurable:false,我们还是可以把 writable 的状态由 true 改为 false,但是无法由 false 改为 true。

enumerable描述符控制的是属性是否会出现在对象的属性枚举中,比如说for..in 循环。如果把 enumerable 设置成 false,这个属性就不会出现在枚举中,虽然仍然可以正常访问它。

6 不变性

1 结合 writable:false 和 configurable:false 就可以创建一个真正的常量属性

2 如果你想禁止一个对象添加新属性并且保留已有属性,可以使用 Object.preventExtensions(..)

3 Object.seal(..) 会创建一个“密封”的对象,这个方法实际上会在一个现有对象上调用Object.preventExtensions(..) 并把所有现有属性标记为 configurable:false。所以,密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以修改属性的值)。

4 Object.freeze(..) 会创建一个冻结对象,这个方法实际上会在一个现有对象上调用Object.seal(..) 并把所有“数据访问”属性标记为 writable:false,这样就无法修改它们的值。你可以“深度冻结”一个对象,具体方法为,首先在这个对象上调用 Object.freeze(..),然后遍历它引用的所有对象并在这些对象上调用 Object.freeze(..)。但是一定要小心,因为这样做有可能会在无意中冻结其他(共享)对象。

7 [[Get]]和[[Put]]

在语言规范中,myObject.a 在 myObject 上实际上是实现了 [[Get]] 操作(有点像函数调用:[[Get]]())。对象默认的内置 [[Get]] 操作首先在对象中查找是否有名称相同的属性,如果找到就会返回这个属性的值。如果没有找到名称相同的属性,会遍历可能存在的 [[Prototype]] 链,也就是原型链。若在原型链上也没有找到,那就返回undefined。

[[Put]] 被触发时,如果已经存在这个属性,[[Put]] 算法大致会检查下面这些内容。

属性是否是访问描述符(参见3.3.9节)?如果是并且存在setter就调用setter。

属性的数据描述符中writable是否是false?如果是,在非严格模式下静默失败,在严格模式下抛出 TypeError 异常。

如果都不是,将该值设置为属性的值。

如果对象中不存在这个属性,[[Put]] 操作会更加复杂。

8 存在性

in 操作符会检查属性是否在对象及其 [[Prototype]] 原型链中。

hasOwnProperty(..) 只会检查属性是否在 myObject 对象中,不会检查 [[Prototype]] 链。

所有的普通对象都可以通过对于 Object.prototype 的委托来访问hasOwnProperty(..), 但 是 有 的 对 象 可 能 没 有 连 接 到 Object.prototype( 通 过Object.create(null) 来创建)。在这种情况下,形如 myObejct.hasOwnProperty(..)就会失败。这时可以使用Object.prototype.hasOwnProperty.
call(myObject,"a")。

9 遍历

for..in 循环可以用来遍历对象的可枚举属性列表(包括 [[Prototype]] 链)。

对于数值索引的数组来说,可以使用标准的 for 循环来遍历值,或者使用for...of循环,for..of 循环首先会向被访问对象请求一个迭代器对象,然后通过调用迭代器对象的next() 方法来遍历所有返回值。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/104375.html

相关文章

  • 笔记-你不知道JS-原型

    摘要:如果存在于原型链上层,赋值语句的行为就会有些不同。中包含的属性会屏蔽原型链上层的所有属性,因为总是会选择原型链中最底层的属性。如果不直接存在于中而是存在于原型链上层时会出现的三种情况。类构造函数原型函数,两个函数通过属性和属性相关联。 1 [[Prototype]] 对于默认的 [[Get]] 操作来说,如果无法在对象本身找到需要的属性,就会继续访问对象的 [[Prototype]] ...

    vincent_xyb 评论0 收藏0
  • 笔记-你不知道JS-原型

    摘要:如果存在于原型链上层,赋值语句的行为就会有些不同。中包含的属性会屏蔽原型链上层的所有属性,因为总是会选择原型链中最底层的属性。如果不直接存在于中而是存在于原型链上层时会出现的三种情况。类构造函数原型函数,两个函数通过属性和属性相关联。 1 [[Prototype]] 对于默认的 [[Get]] 操作来说,如果无法在对象本身找到需要的属性,就会继续访问对象的 [[Prototype]] ...

    AndroidTraveler 评论0 收藏0
  • 你不知道JS》读书笔记---作用域及闭包

    摘要:注此读书笔记只记录本人原先不太理解的内容经过阅读你不知道的后的理解。作用域及闭包基础,代码运行的幕后工作者引擎及编译器。 注:此读书笔记只记录本人原先不太理解的内容经过阅读《你不知道的JS》后的理解。 作用域及闭包基础,JS代码运行的幕后工作者:引擎及编译器。引擎负责JS程序的编译及执行,编译器负责词法分析和代码生成。那么作用域就像一个容器,引擎及编译器都从这里提取东西。 ...

    denson 评论0 收藏0
  • 笔记-你不知道JS-this

    摘要:绑定使用来调用函数,或者说发生构造函数调用时,会自动执行下面的操作。 1 this的概念 this 在任何情况下都不指向函数的词法作用域。作用域对象无法通过 JavaScript代码访问,它存在于 JavaScript 引擎内部。 this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调用时的各种条件。this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方...

    leanote 评论0 收藏0
  • 你不知道javascript》笔记_对象&原型

    摘要:上一篇你不知道的笔记写在前面这是年第一篇博客,回顾去年年初列的学习清单,发现仅有部分完成了。当然,这并不影响年是向上的一年在新的城市稳定连续坚持健身三个月早睡早起游戏时间大大缩减,学会生活。 上一篇:《你不知道的javascript》笔记_this 写在前面 这是2019年第一篇博客,回顾去年年初列的学习清单,发现仅有部分完成了。当然,这并不影响2018年是向上的一年:在新的城市稳定、...

    seasonley 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<