对象:

1、定义对象属性

属性描述符(也称为:数据描述符)

Object.defineProperty(Object,PropertyName,{

    value: 6,

    writable: true,

    configurable: true,

    enumerable: true

})

1.1 Writable

  writable 决定是否可以修改属性的值。

如:

var myObject = {};

     Object.defineProperty( myObject, "a", {
value: 2,
     writable: false, // 不可写!
     configurable: true,
     enumerable: true
} );
myObject.a = 3;
myObject.a; // 还是2,不可修改

  

注:这里把 writable:false 设置成属性不可改变,相当于你定义了一个空操作 setter。严格来说,如果要和writable:false 一致的话,你的 setter 被调用时应当抛出一个 TypeError 错误。

1.2. Configurable
只要属性是可配置的,就可以使用 defineProperty(..) 方法来修改属性描述符。反之,则不可以使用defineProperty方法修改configurable,configurable为false的情况下writable只能从true改成false,但是value的值只受writable的影响,只要writable为true一直都可以修改。

注意:configurable一旦设置成了false,就再也没有机会设置成true了。configurable设置成false之后,属性无法通过delete进行删除操作,不会报错,只是不起作用。

名字起的好,真的是可配置属性,为false之后,不可配置了,writable只是个例外。

var myObject = {
a: 2
};
myObject.a = 3;
myObject.a; // 3
Object.defineProperty(myObject, "a", {
value: 4,
writable: true,
configurable: false, // 不可配置!
enumerable: true
});
console.log(myObject.a); // 4
myObject.a = 5;
console.log(myObject.a); // 5
Object.defineProperty(myObject, "a", {
value: 6,
writable: false,
configurable: false,
enumerable: true
}); // TypeError
console.log(myObject.a) //确实改成了6
myObject.a=7
console.log(myObject.a)
Object.defineProperty(myObject, "a", {
value: 6,
writable: true,
configurable: false,
enumerable: true
}); // TypeError
myObject.a=8
console.log(myObject.a)  

  1.3. Enumerable

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


2、对象不变性

  2.1. 对象常量
  结合 writable:false 和 configurable:false 就可以创建一个真正的常量属性(不可修改、
重定义或者删除),const关键字的实现就是这么来的,只是在window下面添加常量属性。

  2.2. 禁止扩展

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

var myObject = {};
Object.defineProperty(myObject, "FAVORITE_NUMBER", {
value: 42,
writable: false,
configurable: false
});
console.log(myObject)
myObject.b='bbbb';
Object.preventExtensions(myObject);
myObject.c='ccccc'; // 不理会,但不报错
console.log(myObject)
Object.defineProperty(myObject,'d',{
value:'ddddd',
writable:false,
configurable:true
}) // Cannot define property d, object is not extensible
console.log(myObject)

  2.3. 密封
  Object.seal(..) 会创建一个“密封”的对象,这个方法实际上会在一个现有对象上调用
Object.preventExtensions(..) 并把所有现有属性标记为 configurable:false。

所以,密封之后不仅不能添加新属性,也不能重新配置或者删除任何现有属性(虽然可以
修改属性的值)。

  2.4. 冻结
Object.freeze(..) 会创建一个冻结对象,这个方法实际上会在一个现有对象上调用
Object.seal(..) 并把所有“数据访问”属性标记为 writable:false,这样就无法修改它们的值。

你可以“深度冻结”一个对象,具体方法为,首先在这个对象上调用 Object.freeze(..), 然后遍历它引用的所有对象并在这些对象上调用 Object.freeze(..)。但是一定要小心,因为这样做有可能会在无意中冻结其他(共享)对象。

注意:常量和冻结虽然不可写,但是如果值是引用类型的话,它的值只是一个引用地址不可变,但是地址对应的对象依然是可变的,也就是说const定义的变量如果是对象,其值依然是可以赋值进行改变的。

var myObject = {};
var smallobj = {a:'a',b:'b'};
Object.defineProperty(myObject, "FAVORITE_NUMBER", {
value: smallobj,
writable: false,
configurable: false
});
console.log(myObject);
smallobj.c="cccc";
console.log(myObject); // myObject.FAVORITE_NUMBER:{a: "a", b: "b", c: "cccc"} const myOK={a:'abc'}
myOK.b='def';
console.log(myOK) //{a: "abc", b: "def"}

访问描述符:

当你给一个属性定义 getter、setter 或者两者都有时,这个属性会被定义为“访问描述 符”(和“数据描述符”相对)。对于访问描述符来说,JavaScript 会忽略它们的 value 和 writable 特性,取而代之的是关心 set 和 get(还有 configurable 和 enumerable)特性。

Object.defineProperty(Object,PropertyName,{

    get: function(){},

    set: function(){},

    configurable: true,

    enumerable: true

})

给对象定义get和set属性的时候,居然可以这样写,第一次见:

var myObject = {
// 给 a 定义一个 getter
get a() {
return this._a_;
},
// 给 a 定义一个 setter
set a(val) {
this._a_ = val * 2;
}
};
myObject.a = 2;
myObject.a; // 4

  如果你乐意,可以往里面继续添加get b(){},set b(){}。

上面的代码其实和下面是一模一样的:

var myObject = {};
Object.defineProperty(myObject,'a',{
get:function(){
console.log(this)
return this._a_;
},
set:function(val){
this._a_=val*2;
},
configurable:true
}) myObject.a=2;
console.log(myObject.a); //4

  

注:根据MDN描述,如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。


3.属性的存在性

3.1 检查一个属性在对象中是否存在。

  可以用in,hasOwnProperty,区别是in查询属性是否在对象的原型链上,而hasOwnProperty只查询属性是否在对象自身属性中,不考虑继承因素。

3.2 是否在遍历属性中。

  enumerable为true的属性,属于遍历属性,才会出现在for。。。in中。for...in也会查找原型链上所有可以遍历的属性,说白了for...in用的还是in的查找原型链的特性,但是for...in不查enumerable属性为假的属性,但是in会查,只要有,in就返回真。

propertyIsEnumerable(..) 会检查给定的属性名是否直接存在于对象中(而不是在原型链 上)并且满足 enumerable:true。

Object.keys(..) 会返回一个数组,包含所有可枚举属性,Object.getOwnPropertyNames(..) 会返回一个数组,包含所有属性,无论它们是否可枚举

in 和 hasOwnProperty(..) 的区别在于是否查找 [[Prototype]] 链,然而,Object.keys(..) 和 Object.getOwnPropertyNames(..) 都只会查找对象直接包含的属性。

以上内容仅作为笔记,以及一些个人的小见解,不正确之处,欢迎指出,大家一起探讨。

你不知道的JavaScript笔记----对象的更多相关文章

  1. JavaScript笔记:对象及数组

    一.对象 在javascript中,对象是拥有属性和方法的一种基本数据类型 1.创建object 创建object实例有如下两种方式: 使用new操作符后跟object构造函数创建,如下代码: var ...

  2. 你不知道的javaScript笔记(6)

    语法 语句表达式 句子是完整表达某个意思的一组词,由一个或多个短语组成,他们之间由标点符号或者连接词连接起来. 语句相当于句子,表达式相当于短语,运算符则相当于标点符号和连接词. JavaScript ...

  3. 你不知道的javaScript笔记(5)

    原生函数 常用的原生函数 String() Number() Boolean() Array() Object() Function() RegExp() Date() Error() Symbol( ...

  4. 你不知道的javaScript笔记(4)

    类型: JavaScript 有7种内置类型 空值 (null) 未定义(undefined) 布尔值(boolean) 数字(number) 字符串(string) 对象(object) 符号(sy ...

  5. 你不知道的javaScript笔记(7)

    异步:现在与将来 分块的程序 可以把JavaScript 程序写在单独的js 文件中,这个程序是由多个块组成的,这些块 中只有一个是现在执行,其余在捡来执行,最常见的块单位是函数. 例如: funct ...

  6. 你不知道的javaScript笔记(3)

    对象 对象可以通过两种形式定义: 声明形式和构造形式 声明形式语法: var myObj = {key:value} 构造形式语法: var myObj = new Object(); myObj.k ...

  7. 你不知道的javaScript笔记(2)

    this和对象原型 this是一个很特别的关键字,被自动定义在所有函数的作用域中 // foo.count 是0,字面理解是错误的 function foo(num) { console.log(&q ...

  8. 你不知道的javaScript笔记(1)

    规避冲突 function foo(){ function bar(a){ i = 3; console.log(a + i); } for ( var i=0; i < 10; i++){ b ...

  9. 【你不知道的javaScript 上卷 笔记7】javaScript中对象的[[Prototype]]机制

    [[Prototype]]机制 [[Prototype]]是对象内部的隐试属性,指向一个内部的链接,这个链接的作用是:如果在对象上没有找到需要的属性或者方法引用,引擎就 会继续在 [[Prototyp ...

随机推荐

  1. 002_解析go语言中的回调函数

    回调函数是一种特殊的函数写法,在很多场景中发挥广泛的作用.但是对于初学者来说,回调函数是比较头疼的一个东西,不太好懂,笔者研究了一番,以网上的一个例子详细说明一下 首先看一个代码示例(来源于网上) p ...

  2. 会话机制,Cookie和Session详解

    转载自:https://www.cnblogs.com/whgk/p/6422391.html 很大一部分应该知道什么是会话机制,也能说的出几句,我也大概了解一点,但是学了之后几天不用,立马忘的一干二 ...

  3. Loss 总结:IoU loss总结

    object detection 损失:更加接近人眼的损失 what is IoU 如果两个框没有相交,根据定义,IoU=0,不能反映两者的距离大小(重合度).同时因为loss=0,没有梯度回传,无法 ...

  4. akka-typed(9) - 业务分片、整合,谈谈lagom, 需要吗?

    在讨论lagom之前,先从遇到的需求开始介绍:现代企业的it系统变得越来越多元化.复杂化了.线上.线下各种系统必须用某种方式集成在一起.从各种it系统的基本共性分析:最明显的特征应该是后台数据库的角色 ...

  5. 2020-06-13:Redis底层数据结构?

    福哥答案2020-06-13: 福哥口诀法:简链字跳整 压快压 SDS simple synamic string:简单动态字符串.支持自动动态扩容的字节数组 .list :链表 .双端链表.dict ...

  6. .net 跨平台桌面程序 avalonia:从项目创建到打包部署linux-64系统deepin 或 ubuntu。

    介绍: 目前微软还没有跨平台桌面程序的开发框架.github上有一个团队开始自行研发跨平台桌面框架,其中一款叫avalonia.avalonia 采用 Xaml+C#,类似于wpf,可运行于.netf ...

  7. 用Unity3D实现太阳系仿真

    用Unity3D模拟太阳系仿真 模拟要求 写一个程序,实现一个完整的太阳系, 其他星球围绕太阳的转速必须不一样,且不在一个法平面上. 操作步骤 1.创建如下结构 sun 里包括8大行星, 并且设置好距 ...

  8. 03 Arduino-模拟输出与PWM的操作方法

    在arduino开发板上面,标注为PWM的管脚的可以被当作数模转换管脚使用 01 模拟输出  analogWrite(pin, value) pin: 选定的引脚号码  value:取值范围 0-25 ...

  9. 【笔记】 springCloud--Alibaba--服务注册和服务发现

    接着上一次的nacos初步讲解和安装 任意门:https://www.cnblogs.com/Yangbuyi/p/13479767.html 如果启动失败的话 上一篇也是讲解过的. 本文章开始服务注 ...

  10. 【期外】 (一)关于LSH :局部敏感哈希算法

    LSH是我同学的名字,平时我会亲切的称呼他为离骚,老师好,左移(leftshift),小骚骚之类的,最近他又多了一个新的外号:局部敏感哈希(Locally sensitive hashing). 好了 ...