JavaScript 对象:字面量、属性访问与原型链的初步探索

JavaScript 对象:像八卦一样有趣,又像俄罗斯套娃一样精妙

哈喽大家好!今天咱们来聊聊 JavaScript 里一个非常重要的概念——对象。别一听“对象”俩字就觉得严肃,其实 JavaScript 的对象就像生活里的八卦一样有趣,又像俄罗斯套娃一样精妙。

如果你之前接触过其他编程语言,那对象这个概念对你来说应该不陌生。但 JavaScript 的对象,嗯,怎么说呢,有点不一样,就像一个不太按常理出牌的艺术家。

1. 对象字面量:快速上手,先来个“快速约会”

最简单也最常用的创建对象的方式,就是使用对象字面量。你可以把它想象成一个快速约会,直接写出对象的“基本信息”:

let myCat = {
  name: "喵喵",
  color: "白色",
  age: 3,
  meow: function() {
    console.log("喵呜~");
  }
};

瞧,一个活灵活现的猫咪对象就诞生了!这里 myCat 就是一个对象,它有几个属性namecolorage,分别对应猫咪的名字、颜色和年龄。还有一个方法 meow,用来让猫咪发出叫声。

注意,对象字面量用花括号 {} 包裹,属性和值之间用冒号 : 分隔,多个属性之间用逗号 , 分隔。是不是很简单?

就像快速约会一样,对象字面量可以让你快速创建一个对象,定义它的基本属性和行为。但如果你想对这个对象进行更深入的定制,那就需要进一步探索了。

2. 属性访问:八卦的钥匙,打开对象的大门

有了对象,下一步当然是访问它的属性啦!访问属性有两种方式:

  • 点符号 .:就像你用钥匙打开自家大门一样,简单直接。

    console.log(myCat.name); // 输出 "喵喵"
    console.log(myCat.age);  // 输出 3
    myCat.meow();           // 输出 "喵呜~"
  • 方括号 []:当你不知道钥匙长什么样,或者钥匙的名字是动态变化的时候,就得用方括号了。

    let propertyName = "color";
    console.log(myCat[propertyName]); // 输出 "白色"
    
    // 甚至可以用数字作为属性名(虽然不推荐)
    let myObject = {
      0: "第一个",
      1: "第二个"
    };
    console.log(myObject[0]); // 输出 "第一个"

点符号和方括号各有千秋,选择哪个取决于你的具体需求。一般来说,点符号更简洁易读,但方括号更灵活。

3. 对象是动态的:想变就变,灵活得像个演员

JavaScript 的对象非常灵活,你可以在创建之后随时添加、修改或删除属性,就像一个演员可以随时改变自己的角色一样。

  • 添加属性

    myCat.breed = "波斯猫"; // 增加一个 breed 属性
    console.log(myCat.breed); // 输出 "波斯猫"
  • 修改属性

    myCat.age = 4; // 修改 age 属性
    console.log(myCat.age); // 输出 4
  • 删除属性

    delete myCat.color; // 删除 color 属性
    console.log(myCat.color); // 输出 undefined

这种动态性让 JavaScript 对象非常强大,你可以根据需要在运行时调整对象的结构和行为。

4. 原型链:俄罗斯套娃,一层套一层

接下来,咱们要聊聊 JavaScript 对象中最核心也最让人头疼的概念——原型链

你可以把原型链想象成一个俄罗斯套娃,每个套娃里面都藏着一个小套娃,直到最小的那个套娃。

在 JavaScript 中,每个对象都有一个原型对象,这个原型对象也有自己的原型对象,以此类推,就形成了一条链,这就是原型链。

对象的原型对象可以通过 __proto__ 属性来访问(注意,这个属性是非标准的,不推荐直接使用,但为了理解原型链,我们先用它)。

console.log(myCat.__proto__); // 输出 [object Object]

咦?myCat 的原型对象竟然也是一个对象!这个对象是所有 JavaScript 对象的“祖先”—— Object.prototype

Object.prototype 是原型链的顶端,它的原型对象是 null

console.log(myCat.__proto__.__proto__); // 输出 [object Object]
console.log(myCat.__proto__.__proto__.__proto__); // 输出 null

原型链的作用是什么呢?

当你想访问一个对象的属性时,JavaScript 引擎会按照以下步骤进行查找:

  1. 首先,在对象自身查找该属性。
  2. 如果对象自身没有该属性,就到它的原型对象中查找。
  3. 如果原型对象中也没有该属性,就到原型对象的原型对象中查找,以此类推,直到找到该属性或者到达原型链的顶端 null
  4. 如果在整个原型链中都没有找到该属性,就返回 undefined

这种查找机制叫做原型继承。通过原型继承,对象可以访问到原型链上所有对象的属性和方法。

举个栗子:

let myString = "hello";
console.log(myString.toUpperCase()); // 输出 "HELLO"

myString 是一个字符串,但它为什么可以调用 toUpperCase() 方法呢?因为 toUpperCase() 方法定义在 String.prototype 上,而 myString 的原型链中包含了 String.prototype,所以 myString 可以访问到 toUpperCase() 方法。

为什么原型链这么重要?

  • 代码复用:通过原型继承,可以避免重复编写相同的代码。
  • 扩展内置对象:你可以通过修改内置对象的原型对象来扩展它们的功能(但要谨慎使用,避免污染全局作用域)。
  • 实现面向对象编程:原型链是 JavaScript 实现面向对象编程的基础。

5. prototype__proto__:傻傻分不清楚?

原型链中还有两个重要的属性:prototype__proto__。很多人容易把它们搞混,咱们来好好区分一下。

  • prototype:这是函数才有的属性,它指向一个对象,这个对象通常被称为原型对象。当你使用 new 关键字创建一个对象时,这个对象的原型对象就是构造函数的 prototype 属性指向的对象。

  • __proto__:这是对象才有的属性,它指向该对象的原型对象。

简单来说,prototype 是函数的“身份证”,__proto__ 是对象的“族谱”。

举个栗子:

function Person(name, age) {
  this.name = name;
  this.age = age;
}

Person.prototype.sayHello = function() {
  console.log("你好,我是" + this.name);
};

let person1 = new Person("张三", 20);
let person2 = new Person("李四", 22);

person1.sayHello(); // 输出 "你好,我是张三"
person2.sayHello(); // 输出 "你好,我是李四"

console.log(person1.__proto__ === Person.prototype); // 输出 true
console.log(person2.__proto__ === Person.prototype); // 输出 true

在这个例子中,Person 是一个构造函数,它的 prototype 属性指向一个对象,这个对象包含一个 sayHello 方法。person1person2 是通过 new Person() 创建的对象,它们的 __proto__ 属性都指向 Person.prototype,因此它们都可以访问到 sayHello 方法。

6. 总结:对象是 JavaScript 的灵魂

JavaScript 的对象就像一个神秘的盒子,里面充满了惊喜和挑战。掌握了对象,你就掌握了 JavaScript 的灵魂。

  • 对象字面量:快速创建对象,适合简单的场景。
  • 属性访问:用点符号或方括号访问对象的属性。
  • 动态性:对象的属性可以随时添加、修改或删除。
  • 原型链:对象之间继承关系的纽带,实现代码复用和扩展。
  • **prototype__proto__:区分函数的“身份证”和对象的“族谱”。

希望这篇文章能让你对 JavaScript 对象有一个更深入的理解。记住,学习编程就像学习一门外语,需要不断地练习和实践。多写代码,多思考,你就能成为 JavaScript 对象的高手!

最后,送给大家一句名言(我自己编的):“理解了对象,你就理解了 JavaScript 的一半;理解了原型链,你就理解了 JavaScript 的全部!”

下次见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注