当谈到 JavaScript 编程语言时,对象是其中一个最基本且最重要的概念之一。对象是 JavaScript 中用于存储和组织数据的基本机制之一。本文将探讨 JavaScript 中对象的基本概念、创建对象的不同方法以及如何使用对象来组织和操作数据,以及其中需要注意的地方。在讲包装类时,要先讲解对象,因为这两者密不可分。
什么是对象?
在 JavaScript 中,对象是一种复合值,它可以存储多个键值对(也称为属性)。每个属性都有一个名称(键)和一个相关联的值。这些值可以是基本类型(如字符串、数字、布尔值等),也可以是其他对象,甚至是函数。(这说的太表面了,学过c++编程语言的人,对这个概念可以理解的很清楚,刚了解'对象'的人可以把对象当做一个物种,例如人类,比作我们自己这个物种)
对象是动态的,这意味着您可以随时添加、删除或修改其属性。这使得对象成为一种非常灵活和强大的数据结构,可用于表示各种复杂的数据集合。
创建对象
JavaScript 中有几种创建对象的方法。以下是其中的一些:
1. 字面量表示法
csharp
let person = {
name: "John", // 字符串
age: 30, // 数字
isStudent: false // 布尔值
};
2. 使用构造函数
ini
function Person(name, age, isStudent) { // 首字母大写或小写都行,但是大写能表现你定义的是一个构造函数,建议大写,别人也能看得懂
this.name = name;
this.age = age;
this.isStudent = isStudent;
}
let person1 = new Person("John", 30, false); // 实例化对象person
let person2 = new Person("Jerry", 18, true);
请问这两个实例化对象一样吗?不一样,就比如你和你室友都是人,但你和他不是一样的人,因为你和他的身高,体重,性格和爱好都会不同。
构造函数本身没有return返回值,但它却能复制给实例化对象,主要依靠new这个关键字,你可以把上面一个过程这样看:
kotlin
function Person(name, age, isStudent) {
var this = {
this.name = name;
this.age = age;
this.isStudent = isStudent;
}
return this
}
这样看,你也就能理解为什么没有return也可以返回值,是new完成了像这样的过程。
构造函数new的过程步骤:
- new会在构造函数中创建一个this对象上
- 执行函数中代码的逻辑 (相当于往this对象上添加属性)
- return this 对象
3. 使用 Object 构造函数
ini
let person = new Object(); // Object首字母要大写
person.name = "John";
person.age = 30;
person.isStudent = false;
这是调用系统自带的构造函数
访问对象属性
要访问对象的属性,可以使用点符号或方括号表示法:
arduino
console.log(person.name); // 输出: John
console.log(person["age"]); // 输出: 30
如果是访问不存在的属性,会出现什么?
arduino
console.log(person.identity); // 输出undefined
很多人会以为显示undefined很正常,恰恰相反,这个结果很不正常,它不应该报错吗,你又会觉得报错和undefined都差不多,其实差了十万八千里,你可以在全局里,写一段输出不存在的变量console.log(a)
;,看看结果,这段代码会报错而不是undefined,经过这两种情况的对比,你就会意识到里面有大文章。不急,我只是在这里稍微点拨一下,这个与包装类和原型链有关,后面的内容有包装类,下篇文章写原型链。
先放解释:
当您尝试访问一个对象中不存在的属性时,JavaScript 引擎会尝试在对象的原型链上查找该属性。如果在原型链上找不到该属性,JavaScript 将返回 undefined
。
JavaScript 对象的属性访问是通过原型链进行的。在 JavaScript 中,基本数据类型(如字符串、数字、布尔值等)不是对象,但可以像对象一样访问属性和方法。这是因为 JavaScript 会自动为基本数据类型创建对应的包装对象,这些包装对象拥有原型链,可以访问其对应的原始值。
例如,当您访问一个字符串的属性时,JavaScript 会自动将该字符串转换为一个临时的字符串对象,然后在该对象上查找属性。如果该属性不存在,则返回 undefined
。这种自动创建包装对象的行为称为"自动装箱"。
因此,包装类和原型链的机制共同作用,使得在 JavaScript 中访问对象中不存在的属性时返回 undefined
。
修改和添加属性
ini
person.age = 35; // 修改属性值
person["isMarried"] = true; // 添加新属性 或 person.isMarried = true
下面这里有些人可能会搞混:
ini
var abc = 'sex'
person.abc = '男'
console.log(abc)
请问是添加了一个key为abc,value为'男'的属性,还是添加了一个key为sex,value为'男'的属性,
你可以自己试一下,印象会比较深,答案是前一种。
如果你想写出后一种,你可以这样写:
arduino
person[abc] = '男'
删除属性
arduino
delete person.isStudent;
包装类 --- 隐式的过程
原始值是不能拥有属性和方法的。属性和方法是对象独有的。原始类型定义的就是原始值,原始类型有:Numbr,String,undefined,None,boll。
dart
var num = new Number(123)
num.abc = 'hello'
console.log(num.abc); // 123
console.log(num * 2); // 246
num被赋值为123,说明这是原始值,但是你又使用了new关键字,使num成了个对象,添加属性,输出属性也就在理。当num*2时,执行引擎才发现你是想把num当成数字看,所以又转换成了Number类型。这是由于new带来的影响
dart
var num = 123
num.abc = 'hello'
console.log(num) // undefined
上面这段代码没有new,而是直接声明了一个num数字,本来num一开始就是Number类型,然后是你把num当成了对象,给num加了属性,执行引擎执行的时候突然发现这是一个Number,所以又清除了之前你把num当做对象的行为,你可以把这个过程这么看:
javascript
new Number(123).abc = 'hello'
delete new Number(123).abc
console.log(num.abc); // undefined
我们称上面这个过程为包装类
看下面两段代码:
ini
var arr = [1,2,3,4,5,6]
arr.length = 2
console.log(arr); // [1,2]
ini
var str = 'abcde'
str.length = 2
console.log(str) // 'abcde'
对比后,就会困惑为什么会这样?
其实就是包装类的作用,arr和str本来就是原始类型,但执行引擎会把字符串看做对象,而不会把数字看成对象,所以当执行引擎最后发现str是原始类型后,就会把前面的行为删除,这个过程如下:
javascript
new String('abcde').length = 2
delete new String('abcde').length
阿里面试题
ini
// 面试题
var str = 'abc'
str += 1
var test = typeof(str)
if (test.length == 6) {
test.sign = 'typeof 的返回结果是String'
}
console.log(test.sign);
问输出是什么?
解释:
在这段代码中,首先创建了一个字符串变量 str
,其初始值为 'abc'
。然后,使用 +=
运算符将数字 1
连接到字符串后面,相当于将 'abc'
和 1
转换为字符串并拼接,结果为 'abc1'
。接着,使用 typeof
运算符获取 str
的类型,并将结果保存在变量 test
中。
由于 typeof
返回的是一个字符串,所以 test
的值为 'string'
。接下来,代码检查 test.length
是否等于 6
。由于 'string'
的长度为 6
,条件成立,进入 if
语句块。
在 if
语句块中,试图给 test
这个字符串添加一个 sign
属性,值为 'typeof 的返回结果是String'
。然而,JavaScript 执行引擎发现test是个原始类型,所以会删除这个增加属性的行为。因此,test.sign
并不会成功添加属性,它仍然是 undefined
。
最后,通过 console.log(test.sign)
输出 undefined
。
因此,这段代码的输出是 undefined
。
最后
包装类的过程有点缺陷,要讲完原型链,才能补足这个过程,本篇篇幅过长,原型链下篇讲。