Javascript中的对象与包装类,解决百度面试送分题
前言
前端学习中有句话:“Javascript万物皆对象”,这意味着在JavaScript中,几乎所有的东西都是对象,包括基本数据类型(如字符串、数字和布尔值),甚至其中的函数也是对象,它们可以有属性和方法,并且可以作为参数传递给其他函数。对象在js中起着至关重要的作用。接下来通过面试题解析了解对象和包装类。
正文
var str = 'asdfg'
str += 1
var test = typeof(str)
if (test.length == 6) {
test.sign = 'typeof的返回值可能为String'
}
console.log(test.sign)
快速思考一下这送分题的答案,答案是undefined
至于为什么?让我们细细研究
介绍下对象
基本的JavaScript对象类型:
- 原始类型包装对象:字符串(String)、数字(Number)、布尔值(Boolean)等,它们都有对应的构造函数,可以将原始类型转换为对象。
- 引用类型:对象(Object)、数组(Array)、函数(Function)、日期(Date)等,它们是由构造函数创建的复杂数据结构。
更加细节一点就还有特殊对象以及宿主对象。
对象是 JavaScript的基础。在 JavaScript 中一共有六种主要类型(术语是“语言类型”):
- string
- boolean
- number
- null
- undefined
- object
注意,简单基本类型(string、boolean、 number、null 和 undefined)本身并不是对象。
其实JavaScript中有许多特殊的对象子类型,我们可以称之为复杂基本类型。
函数就是对象的一个子类型(从技术角度来说就是“可调用的对象”)。JavaScript 中的函数本质上和普通的对象一样(只是可以调用),所以可以像操作其他对象一样操作函数(比如当作另一个函数的参数)。
数组也是对象的一种类型,具备一些额外的行为。只不过数组中内容的组织方式比一般的对象要稍微复杂一些。
因此JavaScript中“万物皆是对象”,这句话显然是错误的。
对象的创建
对象可以通过两种形式定义:声明(文字)形式和构造形式
1、声明(文字)形式创建对象字面量
var obj = {
key:value
}
2、创建对象实例,对象类型的构造函数
var obj2 = new Object()
构造函数可以自定义
function Car(color){
this.name = 'bba'
this.hight = 1400
this.long = 3000
this.color = color
this.weight = 1000
}
new关键字
构造函数就是一种特殊的函数,只有在new关键字调用后才会创建一个新的对象,并将这个对象与构造函数关联起来。
new 的过程发生了什么
- 先创建一个object空对象{}
- 将构造函数constructor,以new的方式运行
- this 指向实例,运行的过程就是实例逐渐添加属性的过程
- 最后默认返回对象
包装类
在 JavaScript 中,为了便于操作基本类型值,ECMAScript 提供了一些特殊的引用类型,也称为基本包装类型,包括 Boolean、Number 和 String 等。
基本包装类型的主要作用是在后台自动创建对应的对象,以便对基本类型值进行操作。每当读取一个基本类型值时,JavaScript 引擎会自动创建一个对应的基本包装类型对象,从而可以调用一些方法来操作这些数据。这种转换是临时的,调用完成后,这些临时创建是包装对象会被立即销毁。
于是可以解释以下代码的运行
var num = 4
//相当于new Number(4)
num.len=5
// 相当于new Number(4).len=5
// 接着引擎 delete num.len 就算增加了属性也会立即删除
console.log(num.len);//输出的是undefined 而不是报错
但这时便会思考,为什么是undefined
而不是直接输出5
呢?
这是因为:原始值是不允许拥有属性和方法,只有对象才能拥有属性和方法,这种隐式的过程就称之为包装类
那我们再往下看
var str = 'sadf' //相当于new String('sadf')
console.log(str.length);
//
那这里的结果是4
为什么不是undefined
?不是说了原始值是不允许拥有属性和方法吗?
解释为:字符串是原始值,而字符串对象没有length
属性,但它经历了new
过程,相当于new String('sadf')
String这种基本包装类型它具有一些属性和方法,如 length 属性表示字符串的长度
在 JavaScript 中,Boolean、Number 和 String 具有与各自基本类型相应的特殊行为,具体如下:
Boolean 类型:Boolean 类型是布尔值对应的引用类型。它重写了 valueOf() 方法,返回基本类型值 true 或 false;重写了 toString() 方法,返回字符串 "true" 和 "false"。
Number 类型:Number 类型是数字对应的引用类型。它提供了一些方法,如 toFixed() 方法用于保留指定小数位数,toExponential() 方法用于以指数形式表示数字。
String 类型:String 类型是字符串对应的引用类型。它具有一些属性和方法,如 length 属性表示字符串的长度,charAt()、charCodeAt() 方法用于获取指定位置的字符,concat() 方法用于拼接字符串,substr()、substring() 和 slice() 方法用于复制字符串的一部分。
这些特殊行为使得基本类型的值能够像对象一样进行操作,提供了更方便的编程接口。
再来看看这两个例子
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
arr.length = 5;
console.log(arr.length);
var str = 'asdfg' //new String('asdfg')
str.length = 2; //new String('asdfg').length = 2;
console.log(str.length);
为什么这两个输出的结果都为5
呢
字符串是不可变的,意味着你不能改变字符串中的单个字符或其长度。当你尝试设置
str.length = 2
,JavaScript引擎会先增加这个属性,但引擎会立马反应过来并删除这个属性,因为字符串对象不允许有可写属性。由于字符串是原始值,当你访问str.length
时,实际上是在访问字符串的原始长度,而不是对象的属性。
最后回到我们开头的面试题
var str = 'asdfg'
str += 1
var test = typeof(str)
if (test.length == 6) {
test.sign = 'typeof的返回值可能为String'
}
console.log(test.sign)
- 前三行的结果为将test判断为
'asdfg1
被赋予了字符串"string"
- 因此,学习了今天的知识便可以直接秒杀了,因为字符串字面量
"string"
没有.sign
属性。即使在前面的if
语句中尝试设置它,也是无效的,因为字符串字面量是不可变的,也不支持动态添加属性。 - 当执行
console.log(test.sign)
时,结果是undefined
结语
JavaScript 中的包装类(Wrapper Classes)指的是能够将原始数据类型(如字符串、数字、布尔值)包装成对象的构造函数。原始数据类型本身不是对象,但 JavaScript 提供了三个包装类来允许原始数据类型表现得像对象:
String
:将字符串原始值包装成字符串对象。Number
:将数字原始值包装成数字对象。Boolean
:将布尔值原始值包装成布尔对象。
例如:
var str = "Hello"; // 原始字符串
var strObj = new String(str); // 使用String包装类创建字符串对象
var num = 42; // 原始数字
var numObj = new Number(num); // 使用Number包装类创建数字对象
var bool = true; // 原始布尔值
var boolObj = new Boolean(bool); // 使用Boolean包装类创建布尔对象
包装对象提供了一些有用的方法和属性,例如:
String
对象有length
属性和charAt()
、substring()
等方法。Number
对象有toFixed()
、toExponential()
等方法。Boolean
对象通常没有太多额外的方法,因为布尔值只有两个可能的值。
通常,我们可以通过调用原始数据类型的构造函数而不使用 new
关键字来获得类似包装对象的行为,例如:
var strObj = String("Hello"); // 等同于 new String("Hello")
var numObj = Number(42); // 等同于 new Number(42)
var boolObj = Boolean(true); // 等同于 new Boolean(true)
这种方式不会创建一个实际的对象实例,而是返回一个原始类型的值,但提供了一些类似于包装对象的功能。
转载自:https://juejin.cn/post/7376532114105385011