谈谈如何理解对象

使用预定义对象只是面向对象语言的能力的一部分,ECMAScript 真正强大之处在于能够创建自己专用的类和对象。面向对象的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。由于 ECMAScript 中没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。ECMA-262 把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数。”严格来讲,这就相当于说对象是一组没有特定顺序的值。对象的每个属性或方法都有一个名字,而每个名字都映射到一个值。正因为这样(以及其他将要讨论的原因),我们可以把 ECMAScript 的对象想象成散列表:无非就是一组名值对,其中值可以是数据或函数。每个对象都是基于一个引用类型创建的,这个引用类型可以是原生类型,也可以是开发人员定义的类型。

创建自定义对象的最简单方式就是创建一个 Object 的实例,然后再为它添加属性和方法:

let car = new Object();
car.wheel = 4;
car.run = function() {
console.log(this.wheel + ' wheels is running!');
}

属性类型

ECMA-262 第 5 版在定义只有内部才用的特性时,描述了属性的各种特征。ECMA-262 定义这些特性是为了实现 JavaScript 引擎用的,因此在 JavaScript 中不能直接访问它们。为了表示特性是内部值,该规范把它们放在了两对儿方括号中,例如 [[Enumerable]]

ECMAScript 中有两种属性:数据属性访问器属性

** 数据属性 **

数据属性包含一个数据值的位置, 在这个位置可以读取值也能写入, 它有4个特性:

  • [[Configurable]]: 表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性
  • [[Enumerable]]: 表示能否通过 for-in 循环返回属性
  • [[Writable]]: 表示能否修改属性的
  • [[Value]]: 包含这个属性的数据值, 读属性值的时候从这里读, 写入的时候把新值保存在这, 默认值是 undefined

像上面那样直接创建的属性, 包括字面量形式创建的, 除了 [[Value]] 的值被设置成指定的值, 其他的默认值都是 true, 如果要修改属性默认的特性, 需要调用 Object.defineProperty() 方法, 该方法接受3个参数, 属性所在的对象, 属性名, 描述对象, Demo 如下:

let car = {brand: 'Ferrari'};
Object.defineProperty(car, 'brand', {
writable: false
});
car.brand = 'BMW'; // 严格模式这样赋值会报错, 非严格模式下会忽略该赋值
console.log(car.brand); // Ferrari

configurable 也遵循上面的规则, 一旦把属性定义为不可配置就再也不能把它变回可配的了, Object.defineProperty() 只能修改属性的 writable 特性, 其他的修改都会导致错误, 在调用 Object.defineProperty() 时, 如果明确指定 configurable, writable, value, enumerable, 他们的默认值都是 false

** 访问器属性 **

访问器属性不包含数据值, 它包含 gettersetter 函数, 这两个函数也不是必须的, 在读取访问器属性时会调用 getter, 写入时调用 setter, 访问器属性有4个特性:

  • [[Configurable]]: 表示是否能通过 dlelete 删除属性, 能否修改属性的特性, 能否把属性修改为数据属性, 直接在对象上定义的属性这个特性默认是 true
  • [[Enumerable]]: 表示能否通过 for-in 循环返回属性, 直接定义在对象上的属性这个特性默认是 true
  • [[Get]]: 读取属性是调用的函数, 默认是undefined
  • [[Set]]: 写入属性时调用的函数, 默认是undefined

访问器属性不能直接定义, 必须使用 Object.defineProperty() 定义, Demo 如下:

let car = {
_speed: 20,
level: 1
}; Object.defineProperty(car, 'speed', {
get: function() {
return this._speed;
},
set: function(value) {
if(value > 500 || value < 0) {
return console.log('您的车子速度异常');
}
this._speed = value;
this.level = Math.round((value - 20) / 50);
}
}); car.speed = 200;
console.log(car.level); // 4

** 定义多个属性**

为对象定义多个属性可以调用 Object.defineProperties() 方法, 与 Object.defineProperty() 方法不同, 该方法接受2个参数: 要定义属性的对象, 要添加的属性描述集合, Demo 如下:

let car = {};
Object.defineProperties(car, {
_speed: {
value: 20,
configurable: true,
writable: true
},
level: {
value: 1,
configurable: true,
writable: true
},
speed: {
get: function() {
return this._speed;
},
set: function(value) {
if(value > 500 || value < 0) {
return console.log('您的车子速度异常');
}
this._speed = value;
this.level = Math.round((value - 20) / 50);
}
}
});

小结

  • 对象的属性分为两种: 数据属性访问器属性 (函数类型的我们称之为对象的方法)
  • 介绍了 Object.defineProperty()Object.defineProperties() 的使用, 前者接受3个参数, 后者接受2个
  • 介绍了访问器属性的使用, 设置一个属性的值会导致其他属性联动的时候我们可以使用访问器属性

Javascript之谈对象的更多相关文章

  1. 关于JavaScript对象,你所不知道的事(一)- 先谈对象

    这篇博文的主要目的是为了填坑,很久之前我发表了一篇名为关于JavaScript对象中的一切(一) - 对象属性的文章,想要谈一谈JavaScript对象,可那时只是贴了一张关于这个主题的思维导图,今天 ...

  2. javascript是判断对象是否是数组

    JS中的数据类型: 2大类 原始类型:值保存在变量本地的数据类型 5种:Number String Boolean undefined null Number:8bytes 舍入误差-->四舍五 ...

  3. JavaScript 基础回顾——对象

    JavaScript是基于对象的解释性语言,全部数据都是对象.在 JavaScript 中并没有 class 的概念,但是可以通过对象和类的模拟来实现面向对象编程. 1.对象 在JavaScript中 ...

  4. javascript中的对象,原型,原型链和面向对象

    一.javascript中的属性.方法 1.首先,关于javascript中的函数/“方法”,说明两点: 1)如果访问的对象属性是一个函数,有些开发者容易认为该函数属于这个对象,因此把“属性访问”叫做 ...

  5. Javascript 中判断对象为空

    发现了一个巧妙的实现: 需要检查一个对象(Object)是否为空,即不包含任何元素.Javascript 中的对象就是一个字典,其中包含了一系列的键值对(Key Value Pair).检查一个对象是 ...

  6. JavaScript 中的对象

    JavaScript 中的对象 在 JavaScript 中,对象是数据(变量),拥有属性和方法. JavaScript 中的所有事物都是对象:字符串.数字.数组.日期,等等.   访问对象的属性 访 ...

  7. 使用JavaScript的history对象来实现页面前进后退(go/back/forward)。

    我们都知道JavaScript有history对象,主要是用来记录浏览器窗口的浏览记录.但是,JS脚本是不允许访问到这个记录里面的内容(隐私). 常见的用法是: history.back();//返回 ...

  8. javascript类型系统——Math对象

    × 目录 [1]常量 [2]函数 前面的话 javascript使用算术运算符实现基本的算术运算,如果要实现更加复杂的算术运算,需要通过Math对象定义的常量和函数来实现.和其他对象不同,Math只是 ...

  9. javascript中Date对象的应用——简易日历的实现

    × 目录 [1]效果 [2]HTML [3]CSS[4]JS 前面的话 简易日历作为javascript中Date对象的常见应用,用途较广泛.本文将详细说明简易日历的实现思路 效果演示 HTML说明 ...

随机推荐

  1. zip(), dict(), itertools.repeat(), list(迭代器)

    *. zip(), dict() def demo_zip_dict(): keys = ['a', 'b', 'c'] values = [1, 2, 3] entrys = zip(keys, v ...

  2. Eclipse 中的 parameter参数,property属性,preference首选项 区别

    parameter参数 1.配置框架 web.xml <init-param> <param-name>contextConfigLocation</param-name ...

  3. asp.net大文件上传解决方案

    以ASP.NET Core WebAPI 作后端 API ,用 Vue 构建前端页面,用 Axios 从前端访问后端 API ,包括文件的上传和下载. 准备文件上传的API #region 文件上传  ...

  4. R 保存图片——tiff

    tiff(filename = "c:\\aaa.tiff", res = 800, pointsize = 2) plot(1:100) dev.off() tiff(file= ...

  5. Spring Cloud教程(十一)环境变化和刷新范围

    应用程序将收听EnvironmentChangeEvent,并以几种标准方式进行更改(用户可以以常规方式添加ApplicationListeners附加ApplicationListeners).当观 ...

  6. CodeForces - 474D (dp)

    题目:https://vjudge.net/contest/326867#problem/B 题意:有很多个蛋糕,现在你有两种吃蛋糕的吃法,一次吃一个,定为A,一次吃k个定为B,然后问你吃m个蛋糕有多 ...

  7. CSS设置透明背景

    filter: alpha(opacity=40); background-color: rgb(0, 0, 0); background-color: rgba(0, 0, 0, 0.4); 通过改 ...

  8. SQL的一对多,多对一,一对一,多对多什么意思?

    1.一对多:比如说一个班级有很多学生,可是这个班级只有一个班主任.在这个班级中随便找一个人,就会知道他们的班主任是谁:知道了这个班主任就会知道有哪几个学生.这里班主任和学生的关系就是一对多. 2.多对 ...

  9. uva live 7639 Extreme XOR Sum (暴力+二项式)

    题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  10. 小程序框架MpVue踩坑日记(二)

    数据嵌套超过三层或者等于三层的时候 父组件传值给子组件后,如果子组件内的值需要改变 通过this.emit()传值后,父组件的值虽然会改变,但是视图并不会重新渲染 原因就是数据嵌套太多,没有触发ren ...