17Object对象

Object对象

创建对象的三种形式

  1. 创建空对象 var obj1 = new Object(null); var obj2 = new Object(undefined);
  2. 创建一个与给定值对应类型的对象 var obj3 = new Object(100); console.log(obj3); //[Number: 100]
  3. 当以非构造函数形式被调用时,Object 等同于 new Object()。 var obj4 = Object(); //函数调用 var obj5 = new Object(); //构造函数调用

属性描述符

Javascript提供了一个内部数据结构,用于描述对象的值,控制其行为,例如该属性是否可写、是否可配置、是否可修改以及是否可枚举等。这个内部数据结构被称为“属性描述符”。

对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。

数据描述符

默认值

value

该属性对应的值,可以是任何有效的Javascript值(数值,对象,函数等)。

undefiend

writable

当且仅当该属性的writable为true时, valueオ能被赋值运算符改変。

false

configurable

当且仅当该属性的configurable为true时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。

false

enumerable

当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。

false

存取描述符

默认值

get

给属性提供getter的方法,如果没有getter则为undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传人this对象。

set

给属性提供setter的方法,如果没有setter则为undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值

configurable

当且仅当该属性的configurable为true时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。

false

enumerable

当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。

false

获取属性描述符

通过Object.getOwnPropertyNames(object,prop)方法获取属性描述符,其中:

  • object 表示指定属性对应的目标对象
  • prop 表示描述符的目标属性名称
  • 返回值 其属性描述符对象
/**
 * 通过定义对象(属性火方法)这种方式
 * 属性默认都是数据描述符
 */
var obj = {
  name: "张无忌",
};
/**
 * 使用Object.getOwnPropertyNames()方法获取指定属性的描述符
 *  Object.getOwnPropertyNames(object,prop)
 *  object - 表示指定属性对应的目标对象
 *  prop - 表示描述符的目标属性名称
 *  返回值 - 其属性描述符对象
 *
 *
 * */
var result = Object.getOwnPropertyDescriptor(obj, "name");
console.log(result); //{ value: '张无忌', writable: true, enumerable: true, configurable: true }
console.log(result.value); //张无忌

设置属性描述符

设置属性使用Object.defineProperty(obj,prop,desc)方法,他的作用有两个:用于定义目标对象的新属性、修改目标对象的已存在属性。其中:

  • obj 表示目标对象
  • prop 表示目标对象的目标属性名称
  • desc 表示属性描述符,必须是对象的格式。 { value: '' }
  • 返回值 返回传递的对象

设置value值

  1. 修改一个值 var obj = { // 定义对象的同时定义了该属性以及值(可修改,可删除,可枚举) name: "张无忌", }; Object.defineProperty(obj, "name", { value: "周芷若" }); console.log(obj);
  2. 新增一个值 Object.defineProperty(obj, "age", { value: 18, }); console.log(obj.age); //18

与常规方式的区别

  • 如果使用"对象名.属性名 = 值" 可修改,可删除,可枚举
  • 如果使用Object.defineProperty()方法新增属性 不可修改命不可删除以及不可枚举

一旦属性的值是不可修改的,执行修改操作:没有语法错误,但修改无效

由图可以得知:用Object.defineProperty()方法新增属性后,再次修改后输出,值并未发生变化。

设置wriable值

该值为布尔值,默认为false。表示属性值可否被修改。

  1. 修改现有属性 当writable为false时,无法修改其属性。 var obj = { // 定义对象的同时定义了该属性以及值(可修改,可删除,可枚举) name: "张无忌", }; // 修改现有属性 Object.defineProperty(obj, "name", { value: "周芷若", writable: false, }); console.log(obj.name); //周芷若 // 修改name属性值 obj.name = "赵敏"; console.log(obj.name); //周芷若
  1. 新增属性 与修改同理当writable为false时,无法修改其属性。为true时可以修改.

设置configurable值

Booleant值,表示目标属性的描述符是否可以被修改。当且仅当该属性的configurable为true时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除.默认为false

设置enumerable值

var obj = {
  // 定义对象的同时定义了该属性以及值(可修改,可删除,可枚举)
  name: "张无忌",
};
Object.defineProperty(obj, "name", {
  value: "周芷若",
  enumerable: false,
});
console.log(obj.name);

/** 属性描述符enumerable - 控制当前属性是否可被枚举(遍历)
 * 仅能循环遍历对象中可被枚举的属性
 *   * for...in语句
 *   * keys()方法
 * 可以循环遍历对象中可被枚举和不可被枚举的属性
 * getOwnPropertyNames()方法
 */

for (var i in obj) {
  console.log(i);
}

var result1 = Object.keys(obj);
console.log(result1);
var result2 = Object.getOwnPropertyNames(obj);
console.log(result2);

以上代码执行结果:

  1. 属性描述符也可以设置方法,与上述属性设置一模一样。
var obj = {
  sayMe: function () {
    console.log("this is function ");
  },
};
var result = Object.getOwnPropertyDescriptor(obj, "sayMe");
console.log(result);
/*
{
  value: [Function: sayMe],
  writable: true,
  enumerable: true,
  configurable: true
}
*/
Object.defineProperty(obj, "sayMe", {
  value: function () {
    console.log("this is new function");
  },
  writable: false,
});
obj.sayMe(); // this is new function

obj.sayMe = function () {
  console.log("这是张无忌");
};
obj.sayMe(); //this is new function

属性描述符的存取器

  1. get get当获取或访问当前属性时,会调用此方法。 类似数据描述符中的value
    • get方法在被调用时,不能传递任何参数
    • get方法在被调用时,允许传递this关键字
      • this - 表示当前的目标对象
var obj = {
  sayMe: function () {
    console.log("this is function ");
  },
};
var result = Object.getOwnPropertyDescriptor(obj, "sayMe");
console.log(result);
/*
{
  value: [Function: sayMe],
  writable: true,
  enumerable: true,
  configurable: true
}
*/
Object.defineProperty(obj, "sayMe", {
  value: function () {
    console.log("this is new function");
  },
  writable: false,
});
obj.sayMe(); // this is new function

obj.sayMe = function () {
  console.log("这是张无忌");
};
obj.sayMe(); //this is new function
  1. set set方法用于定义当前目标函数的修改功能
    • 该方法接收唯一的一个参数 作为当前目标属性的新的值
    • 通过属性修改操作指定新的值 作为形参对应的实参

    此方法修改值需借助一个变量,例如:

var obj = {
  sayMe: function () {
    console.log("this is function ");
  },
};
var result = Object.getOwnPropertyDescriptor(obj, "sayMe");
console.log(result);
/*
{
  value: [Function: sayMe],
  writable: true,
  enumerable: true,
  configurable: true
}
*/
Object.defineProperty(obj, "sayMe", {
  value: function () {
    console.log("this is new function");
  },
  writable: false,
});
obj.sayMe(); // this is new function

obj.sayMe = function () {
  console.log("这是张无忌");
};
obj.sayMe(); //this is new function
需要注意的是:如果变量没有初始化获取值,那么值是 undefined。
var obj = {
  name: "张无忌",
};
var value; //全局变量
Object.defineProperty(obj, "name", {
  set: function (newvalue) {
    console.log("this is set function ");
    value = newvalue;
  },
});
console.log(obj.name); //undefined

关于get与set的另一种常见写法

var obj = {
  // 存取描述符中的get
  get attr() {
    return "张三";
  },
  set attr(value) {
    console.log("setter:" + value);
  },
};
console.log(obj.attr); //张三
obj.attr = 100; //setter:100

这种写法中,赋值与上方一致,也是定义一个新的变量,然后赋值。此写法结果与用法与上边一致,只是写法不同。

防篡改对象

定义的对象默认在任何时候、任何位置,无论有意义的还是无意义的都可以修改对象的属性或方法。而这些篡改可能会影响对象的内置属性或方法,从而导致对象的正常功能可能无法使用。 Javascript在ES5版本中新増了放置纂改对象的属性或方法的机制,共提供了以下三级保护方式

  • 禁止扩展 禁止为对象扩展新的属性或方法
  • 密封对象 禁止扩展新的属性或方法,禁止配置现有的属性或方法的描述符,仅允许读写属性的值
  • 冻结对象 禁止对对象执行任何修改操作。

禁止扩展

禁止扩展只需要调用Object.preventExtensions(obj)方法即可,参数就是需要禁止的对象.

一旦设置禁止扩展,那么该对象不可新增属性或方法.

  • 使用obj.name方法新增不会报错但无效
  • 使用Object.defineProperty方法新增会报错.

判断对象是否可扩展使用方法Object.isExtensible(obj),参数同样是需要判断的对象.

返回一个布尔值,true表示可被扩展,false表示不可被扩展.

var obj = {};
// 将对象设置禁止扩展
Object.preventExtensions(obj);
// 新增属性或方法无效 -> 语法没有报错
obj.name = "张无忌";
// 此方法新增或修改或报错
// Cannot define property name, object is not extensible
Object.defineProperty(obj, "name", {
  value: "周芷若",
});
console.log(obj);
// 返回布尔值 true表示可扩展 false表示不可扩展
var result = Object.isExtensible(obj);
console.log(result);

密封对象

将对象进行密封调用Object.seal(obj)即可,参数为需要密封的对象.

一旦将对象进行了密封,那么需要注意如下:

  • 不能为该对象新增属性或方法
  • 不能修改该对象的以下属性或方法的描述符
    • configurable
    • enumerable

判断是否是密封对象Object.isSealed(obj),参数同样是需要判断的对象.

返回一个布尔值,true表示被密封了,false表示没有被密封

var obj = {
  name: "张无忌", //可修改
};

// 将该对象进行密封
Object.seal(obj);
/**
 * 将对象进行密封
 * 1. 不能为该对象新增属性或方法
 * 2. 不能修改该对象的属性或方法的描述符(configurable、enumerable)
 */
// // 新增属性
obj.age = 18;
console.log(obj); // { name: '张无忌' }
// // 修改属性
obj.name = "周芷若";
console.log(obj); //{ name: '周芷若' }

// 报错
// Object.defineProperty(obj, "age", {
//   value: 18,
// });
// 修改值
Object.defineProperty(obj, "name", {
  value: "赵敏",
  writable: false,
  //   configurable: true, //不可修改
  //   enumerable: true, //不可修改
});
console.log(obj); //{ name: '周芷若' }
obj.name = "赵敏";
console.log(obj); //{ name: '赵敏' }

冻结对象

将对象进行密封调用Object.freeze(obj)即可,参数为需要冻结的对象.

一旦将对象进行了冻结,那么该对象只能使用,不能做任何修改,包括删除

判断是否是密封对象Object.isFrozen(obj),参数同样是需要判断的对象.

返回一个布尔值,true表示被冻结了,false表示没有被冻结

var obj = {
  name: "张无忌",
};
// 冻结对象
Object.freeze(obj);

// 新增
obj.age = 18;
console.log(obj); //{ name: '张无忌' }
// 修改
obj.name = "周芷若";
console.log(obj); //{ name: '张无忌' }
// 删除
delete obj.name;
console.log(obj); //{ name: '张无忌' }

// 以下方法报错
// Object.defineProperty(obj, "age", {
//   value: 18,
// });
console.log(Object.isFrozen(obj));

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 前端课程——过渡

    Dreamy.TZK
  • 一、初识jQuery

    1.x:兼容ie678,但相对其它版本文件较大,官方只做BUG维护,功能不再新增,最终版本:1.12.4 (2016年5月20日).

    Dreamy.TZK
  • 19原型

    在 Javascript中,函数是一个包含属性和方法的Function类型的对象。而原型( Prototype)就是Function类型对象的一个属性。

    Dreamy.TZK
  • 机器学习 | K-Means聚类算法原理及Python实践

    “聚类”(Clustering)试图将数据集中的样本划分为若干个不相交的子集,每个子集被称为一个“簇”或者“类”,英文名为Cluster。比如鸢尾花数据集(Ir...

    PP鲁
  • 向前、向后、横着走,双足机器人Cassie,靠深度强化学习学会了走路丨论文

    Agility Robotics的双足机器人Cassie,这个没有上半身的机器人,就靠着深度强化学习学会了更灵活的使用自己身体的唯二器官:左腿,和右腿。

    量子位
  • Linux操作系统安装的5种方法以及心得

      其中光盘安装是最普遍的,也是最简单的我就不写了。我安装的这台机器没有光驱,也没有软驱!!!只有网卡和一个128MU盘"o"

    MonroeCode
  • 1.Linux操作系统安装的5种方法以及心得

      安装Linux共有五种方法   1、光盘       2、硬盘   3、NFS 映像   4、FTP   5、HTTP   其中光盘安装是最普遍的,也是最简...

    MonroeCode
  • 安装ClouderaManager以及使用ClouderaManager安装分布式集群的若干细节

    目录 前言 整体介绍 分步安装介绍 总结 一、前言        周末干了近四十个小时中间只休息了五个小时终于成功安装了ClouderaManager以及分布式...

    魏守峰
  • 数据如何驱动网站页面设计和优化

    大数据文摘
  • iOS内存管理-深入解析自动释放池

    iOS开发中的Autorelease机制是为了延时释放对象。自动释放的概念看上去很像ARC,但实际上这更类似于C语言中自动变量的特性。

    梧雨北辰

扫码关注云+社区

领取腾讯云代金券