JavaScript 中的对象和包装类:面试解析与阿里面试题分析
前言
在JavaScript中有句话:万物皆对象。其实本质上在JS这门编程语言当中,任何东西都可以称之为是一个对象。对象在js中起着举足轻重的作用。我们通过面试题解析了解对象和包装类。
正文
面试题
var arr = [1,2,3,4,5]
arr.length = 2
console.log(arr)
var str = 'abcde'
str.length = 2
console.log(str)
分别会输出什么呢?
分别输出[1,2]
和abcde
。
为什么会输出这些那?我们先对对象和包装类进行了解。当我们理解后挑战阿里面试题。
什么是对象
在JavaScript中,除了数字、字符串、数字、undefined和null这五种原始数据类型,其余的都是对象。数字、字符串和布尔值虽然具有一些类似对象的行为,比如有一些方法可以调用,但它们并不是真正意义上的对象。
对象是属性的集合:由一系列的键值对组成,键表示属性名,值表示属性所对应的数据。
对象具有特定行为:可以包含方法(函数)来定义对象的操作。
对象可以可动态修改:可以在对象创建后添加、修改或删除属性。
对象的创建
对象的创建有三种方法:
-
创建对象字面量。
直接使用花括号创建。eg:
var object = {}
优点:代码量少,简便。
-
调用系统自带的构造函数 new Object()。
eg:
var object = new Object()
-
调用自定义的构造函数。
eg:
function People(name, age, sex) { this.name = name this.age = age this.sex = sex } let p1 = new People('小李', 18, 'boy')
优点:可以批量创建对象。
new关键字
构造函数就是一种特殊的函数,只有在new关键字调用后才会创建一个新的对象,并将这个对象与构造函数关联起来。
function People(name, age, sex) {
this.name = name
this.age = age
this.sex = sex
}
let p1 = new People('小李', 18, 'boy')
构造函数被new调用的过程:
- new会在构造函数中创建一个object对象。
- 通过call方法将this指向object对象
- 将object对象的原型指向构造函数的原型。
- 执行函数中的逻辑代码(相当于往object对象上添加属性)。
- 返回object对象。
function People(name, age, sex) {
//new会在构造函数中创建一个this对象
// var object = {}
//通过call方法将this指向object对象
//People.call(object)
//将object对象的原型指向构造函数的原型
//object.__proto__ === People.prototype
//执行函数中的逻辑代码(相当于往object对象上添加属性)
this.name = name
this.age = age
this.sex = sex
//返回object对象
// return object
}
let p1 = new People('a', 18, 'boy')
对象的增删改查
var xm = {
name: '李明',
age: 18,
sex: 'boy',
run: function () {
console.log('I am running')
},
drink: function () {
console.log('I am drinking,cool!')
},
health: 100
}
对该对象进行增删改查操作。
-
增加对象的属性。
有两种方法:
-
方法一:使用点号。
xm.girlFriend = '小美' //添加 girlFriend:'小美' 键值对 ----------------------------------------- var a = 'girlFriend' xm.a = '小美' //添加 a:'小美' 键值对
xm.girlFriend = '小美'
中的girlFriend默认是字符,不是变量。 -
方法二:使用方括号。
var a = 'girlFriend' xm[a] = '小美' //添加 girlFriend:'小美' 键值对 ------------------------------------------ var a = 'girlFriend' xm['a'] = '小美' //添加 a:'小美' 键值对
xm[a] = '小美'
中的a默认是变量,加上引号变成字符。该方法的优点:可以通过变量添加对象属性。
-
-
删除对象的属性。
delete xm.age
-
修改对象的属性。
xm.age = 30
-
查对象的属性。
xm.run() ---------------------------------------------- console.log(xm.age)
小tips:如果访问对象上不存在的属性,得到的结果是undefined,并不会报错。
包装类
包装类是JavaScript中为原始数据类型(如数字、字符串、布尔值)提供对象形式的类。常见的包装类有Number(用于数字类型)、String(用于字符串类型)和Boolean(用于布尔值类型)。包装类可以让原始数据类型具有一些类似对象的方法和属性。
当我们在基本数据类型上调用对象方法时,JavaScript会根据需要隐式地创建相应的包装对象,然后在该对象上调用方法。这种转换是临时的,调用完成后,这些临时创建是包装对象会被立即销毁。
eg1:
var str = '1234'
console.log(str.length)//输出:4
为什么会输出4呢?明明说过原始数据类型是不能拥有属性和方法,怎么string类型会有length属性呢?
因为str是一个对象。
var str = '1234'
//在v8的执行过程中是这样的:str = new String ('1234')
在执行过程中,JavaScript引擎把str执行为对象,而不是原始数据类型。
eg2:
var num = 987
num.str = 'hello'
console.log(num.str)
结果会是什么呢?
结果为undefined
,并没有报错。因为原始数据类型是不能拥有属性和方法的,属性和方法是对象独有的。
在JavaScript引擎执行过程中,这段代码是这样的:
new Number(987).str = 'hello'
//当我们创建一个num数字类型时,JavaScript引擎会创建一个对象;并且添加str:'hello'键值对。
delete new Number(987).str
//JavaScript会发现我们想创建的是一个原始数据类型,所以会删除str属性。
console.log(num.str)//输出:undefined
//访问对象上不存在的属性,得到的结果是undefined
还记得上面的小tips吗,如果访问对象上不存在的属性,得到的结果是undefined,并不会报错。
这个隐式的过程就是包装类
eg3:
var num = new Number(123)
num.abc = 'hello'
console.log(num.abc)//输出:hello
console.log(num*2)//输出:246
console.log(num.abc)
输出hello,我们可以理解,因为num是通过构造函数创建的实例对象,使用可以添加对象属性。
但是console.log(num*2)
输出:246,难以理解。

对象乘以数字应为NaN,为什么这里却是246呢?
因为当num(Number构造函数创建的实例对象)参加四则运算时,JavaScript引擎会把num当作原始数据类型执行。
解答面试题
var arr = [1,2,3,4,5]
arr.length = 2
console.log(arr)
var str = 'abcde'
str.length = 2
console.log(str)
解析:
arr是数组,也就是对象。所以可以通过arr.length = 2
修改数组的长度。
str.length = 2
被当作为包装类的执行过程,会被移除。
var str = 'abcde'
str.length = 2
//这两行代码在v8执行过程中被执行为:new String('abcde').length = 2
//但是v8意识到我们想创建的是字符串字面量,并不是对象。所以便删除了length属性
//delete new String('abcde').length
console.log(str)
JavaScript引擎执行的代码为:
new String('abcde').length = 2
delete new String('abcde').length
console.log(str)
实战阿里面试题
var str = 'abc'
str += 1
var test = typeof(str)
if (test.length == 6) {
test.sign = 'typeof 的返回结果是String'
}
console.log(test.sign);
结果为undefined
。
解析:
- 首先,定义了一个字符串变量 str并赋值为 'abc'。
- 然后,执行了
str += 1
,这里会进行隐式类型转换,将数字 1加到字符串 'abc'上,得到结果 'abc1'。 - 接着,使用 typeof 操作符获取 str 的类型,得到结果是字符串 "string"。
- 在 if 条件判断中,检查 typeof 的结果字符串的长度是否为 6(即 "string" 的长度),条件成立。
- 然而,当尝试给typeof 的返回结果(字符串)添加属性 sign 时,V8会为test添加sign属性,但是在v8意识到tset为原始数据类型后,便删除了sign属性。
- 如果访问对象上不存在的属性,得到的结果是undefined。
转载自:https://juejin.cn/post/7366082235243921445