找回密码
 立即注册
首页 业界区 业界 Web前端入门第 61 问:JavaScript 各种对象定义与对象取 ...

Web前端入门第 61 问:JavaScript 各种对象定义与对象取值方法

昝沛珊 前天 10:20
曾经有人说 JS 语言中万物皆对象,虽然这种说法不一定完全准确,但也有一定的道理。原因是 JS 的语法看起来所有的数据类型都像是一个对象,包括原始类型。
  1. const a = 1.234;
  2. console.log(a.toString());
  3. console.log(a.valueOf());
  4. console.log(a.toFixed(2));
  5. console.log(Number.prototype); // 查看所有 Number 类型的原型链方法属性
  6. const b = '前端路引';
  7. console.log(b.length);
  8. console.log(b.substring(2));
  9. console.log(b.padEnd(10, '*')); // 后填充 * 字符
  10. console.log(String.prototype); // 查看所有 String 类型的原型链方法属性
  11. const c = true;
  12. console.log(c.toString());
  13. console.log(Boolean.prototype); // 查看所有 Boolean 类型的原型链方法属性
复制代码
以上展示了 Number、String、Boolean 三种原始类型的方法。a.xxx() 这种写法就表示 xxx 是 a 的方法。
一般定义在对象上的 函数 都称之为 对象方法,使用语法: xxx.yyy()。对象除了方法还有 对象属性,使用语法: xxx.yyy。
方法和属性的区别是:方法是函数,属性是值。
举个例子:
  1. const obj = {
  2.   name: '前端路引', // 对象属性
  3.   age: 1, // 对象属性
  4.   sayHi() { // 对象方法
  5.     console.log(`我是${this.name},我今年${this.age}岁`);
  6.   }
  7. }
复制代码
以上是一个 JS 的对象字面量定义方式,除了最常用的对象字面量,还可以像 Array 一样,使用构造函数来定义对象,也可以使用 Class 自定义对象。
对象定义

JS 的对象定义可比 数组 的花样多多了,下面来一一展示。
对象字面量

JS 的对象值与数组一样,无任何限制,可以是任意值,包括函数、数组、对象、undefined、null、NaN 等。
  1. const dynamicKey = 'dynamicKey';
  2. const fnKey = () => {};
  3. const obj1 = {
  4.   name: '前端路引',
  5.   age: 1,
  6.   'favorite-color': 'blue', // 含特殊字符的键需用引号包裹
  7.   [Symbol('id')]: 123, // Symbol 作为键
  8.   [dynamicKey]: 'value', // 使用动态变量作为属性名
  9.   [fnKey]: '使用函数作为键名称',
  10.   greet() { // 方法简写(ES6+)
  11.     console.log('Hello!');
  12.   },
  13.   say: function () { // 函数
  14.     console.log('Hi!');
  15.   }
  16. };
复制代码
构造函数

虽然此方法使用较少,但这种方式也可以用来定义一个对象。以下代码与上面的对象字面量定义的对象一样:
  1. const dynamicKey = 'dynamicKey';
  2. const fnKey = () => {};
  3. const obj2 = new Object();
  4. obj2.name = '前端路引';
  5. obj2.age = 1;
  6. obj2['favorite-color'] = 'blue';
  7. obj2[Symbol('id')] = 123;
  8. obj2[dynamicKey] = 'value';
  9. obj2[fnKey] = '使用函数作为键名称';
  10. obj2.greet = function () {
  11.   console.log('Hello!');
  12. }
  13. obj2.say = function () {
  14.   console.log('Hi!');
  15. }
复制代码
Object.create()

使用对象的静态方法 Object.create() 来创建对象。
静态方法和对象原型链方法的区别是:静态方法属于对象本身,对象原型链上的方法属于对象实例。
看例子:
  1. const obj3 = Object.create({ // 使用静态方法创建对象
  2.   name: '前端路引',
  3. })
  4. obj3.toString() // 调用原型链方法,也称为实例方法
复制代码
Object.create 多用于继承一个对象,扩展原有对象的功能:
  1. const obj4 = {
  2.   name: '前端路引',
  3. }
  4. const obj5 = Object.create(obj4);
  5. obj5.age = 1;
  6. obj5['favorite-color'] = 'blue';
复制代码
自定义构造函数

除了使用 JS 提供的内置构造函数,还可以自定义构造函数来创建一个对象。比如:
  1. function WeChat () {
  2.   this.name = '前端路引';
  3.   this.age = 1;
  4.   this['favorite-color'] = 'blue';
  5. }
  6. const obj6 = new WeChat();
复制代码
function 关键字可不止用于函数定义,还能用来自定义构造函数,这是在 ES6 出现之前自定义类最常用的方式。
Class

为了消除语法歧义,ES6 引入了 Class 定义类,再通过 new 关键字创建实例对象,这种方式完全像是 function 的语法糖。
  1. class WeChat {
  2.   constructor() {
  3.     this.name = '前端路引';
  4.     this.age = 1;
  5.     this['favorite-color'] = 'blue';
  6.   }
  7.   say() {
  8.     console.log('Hi!');
  9.   }
  10. }
  11. const obj7 = new WeChat();
复制代码
对象取值

对象的取值方法也多得眼花缭乱,下面一一展示。
点语法

常规属性可以使用 . 取值,比如:
  1. const obj1 = {
  2.   name: '前端路引',
  3.   age: 1,
  4.   'favorite-color': 'blue',
  5.   say() {
  6.     console.log('Hi!');
  7.   }
  8. }
  9. console.log(obj1.name); // 获取属性值
  10. console.log(obj1.say()); // 调用方法
复制代码
方括号取值

. 语法有个问题,比如上面对象中 favorite-color 属性,如果直接使用 obj1.favorite-color,会报错,因为 - 会被当做减号处理,导致报错 ReferenceError: color is not defined。
这时候可以把对象当做数组来处理,使用方括号 [] 取值,比如:
  1. const obj1 = {
  2.   name: '前端路引',
  3.   age: 1,
  4.   'favorite-color': 'blue',
  5.   say() {
  6.     console.log('Hi!');
  7.   }
  8. }
  9. console.log(obj1['favorite-color']); // 获取属性值
  10. console.log(obj1['say']()); // 调用方法
复制代码
使用方括号取值时,如果属性名是动态的,可以使用变量来取值,比如:
  1. const dynamicKey = 'dynamicKey';
  2. const obj1 = {
  3.   [dynamicKey]: '前端路引',
  4. }
  5. console.log(obj1[dynamicKey]);
复制代码
解构赋值

作为 ES6 引入的新特性,此写法如果不了解,那么代码可能都看不懂。
  1. const obj1 = {
  2.   name: '前端路引',
  3.   age: 1,
  4. }
  5. const { name, age, up = '微信公众号' } = obj1;
  6. console.log(name, age);
  7. // 解构赋值,可以添加默认值,如果找不到属性,则使用默认值
  8. console.log(up);
复制代码
Object 静态方法

Object 自身还提供了一些静态方法,用于获取数组的键值。
  1. const obj1 = {
  2.   name: '前端路引',
  3.   age: 1,
  4. }
  5. const keys = Object.keys(obj1);    // 返回所有可枚举属性名数组
  6. const values = Object.values(obj1);// 返回所有值数组
  7. const entries = Object.entries(obj1); // 返回键值对数组
  8. console.log(keys); // ['name', 'age']
  9. console.log(values); // ['前端路引', 1]
  10. console.log(entries); // 二维数组  [['name', '前端路引'], ['age', 1]]
复制代码
Getter / Setter 方法

使用 get 方法,可以设置对象的计算属性,用于拦截对象的取值,比如:
  1. const obj1 = {
  2.   firstName: '微信公众号:',
  3.   lastName: '前端路引',
  4.   get name() {
  5.     return `${this.firstName}:${this.lastName}`; // 微信公众号::前端路引
  6.   },
  7.   set name(value) {
  8.     [this.firstName, this.lastName] = value.split(':');
  9.   }
  10. }
  11. console.log(obj1.name); // 微信公众号:前端路引
  12. obj1.name = '前端路引:微信公众号';
  13. console.log(obj1.name); // 前端路引:微信公众号
复制代码
原型链访问

如果取的属性对象本身不存在,则会顺着原型链查找,直到找到为止,比如:
  1. const obj1 = {
  2.   name: '前端路引',
  3.   age: 1,
  4. }
  5. console.log(obj1.toString()); // toString 方法不在对象本身,是 Object 原型链上的方法,也可以使用取值语法访问
复制代码
可选链

ES2020 引入了可选链,用于解决对象取值时,如果属性不存在,会报错的问题,比如:
  1. const obj1 = {
  2.   name: '前端路引',
  3.   age: 1,
  4. }
  5. // 如果直接取值,将会报错 TypeError: Cannot read properties of undefined (reading 'city')
  6. console.log(obj1.address.city);
  7. // 使用可选链,如果属性不存在,则返回 undefined,不会报错
  8. console.log(obj1?.address?.city);
复制代码
写在最后

以上已包含绝大多数应用场景,但是也会有一些不太常用的写法未包含,比如 Reflect.get(obj, 'a')。作为入门条件,掌握以上内容已经完全够用。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册