likes
comments
collection
share

你真的懂包装类吗......

作者站长头像
站长
· 阅读数 30

当谈到 JavaScript 编程语言时,对象是其中一个最基本且最重要的概念之一。对象是 JavaScript 中用于存储和组织数据的基本机制之一。本文将探讨 JavaScript 中对象的基本概念、创建对象的不同方法以及如何使用对象来组织和操作数据,以及其中需要注意的地方。在讲包装类时,要先讲解对象,因为这两者密不可分。

什么是对象?

在 JavaScript 中,对象是一种复合值,它可以存储多个键值对(也称为属性)。每个属性都有一个名称(键)和一个相关联的值。这些值可以是基本类型(如字符串、数字、布尔值等),也可以是其他对象,甚至是函数。(这说的太表面了,学过c++编程语言的人,对这个概念可以理解的很清楚,刚了解‘对象’的人可以把对象当做一个物种,例如人类,比作我们自己这个物种)

对象是动态的,这意味着您可以随时添加、删除或修改其属性。这使得对象成为一种非常灵活和强大的数据结构,可用于表示各种复杂的数据集合。

创建对象

JavaScript 中有几种创建对象的方法。以下是其中的一些:

1. 字面量表示法

let person = {
    name: "John",  // 字符串
    age: 30,  // 数字
    isStudent: false  // 布尔值
    
};

2. 使用构造函数

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这个关键字,你可以把上面一个过程这样看:

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

这样看,你也就能理解为什么没有return也可以返回值,是new完成了像这样的过程。

构造函数new的过程步骤:

  1. new会在构造函数中创建一个this对象上
  2. 执行函数中代码的逻辑 (相当于往this对象上添加属性)
  3. return this 对象

3. 使用 Object 构造函数

let person = new Object();  // Object首字母要大写
person.name = "John";
person.age = 30;
person.isStudent = false;

这是调用系统自带的构造函数

访问对象属性

要访问对象的属性,可以使用点符号或方括号表示法:

console.log(person.name); // 输出: John
console.log(person["age"]); // 输出: 30

如果是访问不存在的属性,会出现什么?

console.log(person.identity);  // 输出undefined

很多人会以为显示undefined很正常,恰恰相反,这个结果很不正常,它不应该报错吗,你又会觉得报错和undefined都差不多,其实差了十万八千里,你可以在全局里,写一段输出不存在的变量console.log(a);,看看结果,这段代码会报错而不是undefined,经过这两种情况的对比,你就会意识到里面有大文章。不急,我只是在这里稍微点拨一下,这个与包装类和原型链有关,后面的内容有包装类,下篇文章写原型链。

先放解释:

当您尝试访问一个对象中不存在的属性时,JavaScript 引擎会尝试在对象的原型链上查找该属性。如果在原型链上找不到该属性,JavaScript 将返回 undefined

JavaScript 对象的属性访问是通过原型链进行的。在 JavaScript 中,基本数据类型(如字符串、数字、布尔值等)不是对象,但可以像对象一样访问属性和方法。这是因为 JavaScript 会自动为基本数据类型创建对应的包装对象,这些包装对象拥有原型链,可以访问其对应的原始值。

例如,当您访问一个字符串的属性时,JavaScript 会自动将该字符串转换为一个临时的字符串对象,然后在该对象上查找属性。如果该属性不存在,则返回 undefined。这种自动创建包装对象的行为称为“自动装箱”。

因此,包装类和原型链的机制共同作用,使得在 JavaScript 中访问对象中不存在的属性时返回 undefined

修改和添加属性

person.age = 35; // 修改属性值
person["isMarried"] = true; // 添加新属性  或 person.isMarried = true

下面这里有些人可能会搞混:

var abc = 'sex'
person.abc = '男'
console.log(abc)

请问是添加了一个key为abc,value为‘男’的属性,还是添加了一个key为sex,value为‘男’的属性,

你可以自己试一下,印象会比较深,答案是前一种。

如果你想写出后一种,你可以这样写:

person[abc] = '男'  

删除属性

delete person.isStudent;

包装类 --- 隐式的过程

原始值是不能拥有属性和方法的。属性和方法是对象独有的。原始类型定义的就是原始值,原始类型有:Numbr,String,undefined,None,boll。

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带来的影响

var num = 123
num.abc = 'hello'

console.log(num)  // undefined

上面这段代码没有new,而是直接声明了一个num数字,本来num一开始就是Number类型,然后是你把num当成了对象,给num加了属性,执行引擎执行的时候突然发现这是一个Number,所以又清除了之前你把num当做对象的行为,你可以把这个过程这么看:

new Number(123).abc = 'hello'
delete new Number(123).abc
console.log(num.abc);  // undefined

我们称上面这个过程为包装类

看下面两段代码:

var arr = [1,2,3,4,5,6]
arr.length = 2
console.log(arr);  // [1,2]
var str = 'abcde'
str.length = 2
console.log(str)  // 'abcde'

对比后,就会困惑为什么会这样?

其实就是包装类的作用,arr和str本来就是原始类型,但执行引擎会把字符串看做对象,而不会把数字看成对象,所以当执行引擎最后发现str是原始类型后,就会把前面的行为删除,这个过程如下:

new String('abcde').length = 2
delete new String('abcde').length

阿里面试题

// 面试题
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

最后

包装类的过程有点缺陷,要讲完原型链,才能补足这个过程,本篇篇幅过长,原型链下篇讲。

转载自:https://juejin.cn/post/7366216150710370341
评论
请登录