包装类 基本数据类型没有属性和方法? 你不知道的javascript 大厂面试常考题

197 阅读6分钟

包装类 你不知道的Javascript 大厂面试题

哈喽哈喽大家好,我是你们的金樽清酒。我们知道js的数据类型分为两大类,基本数据类型(原始类型)和引用数据类型(复杂数据类型)。为什么会有这样的划分呢?大家有没有想过这两种数据类型有什么区别呢?那让我们一起往下看了解一下吧。

一、了解数据类型

  • 1.基本数据类型

let num =123 数字型

let str ='hello' 字符型

let flag =true 布尔型

let un =undefined 未定义

let nu =null 空值 当然ES6中有新加了两种数据,这里就不多做解释。

  • 复杂数据类型

let obj ={}

let fn= function(){}

let arr = []

let data =new DataTransfer()

对象(复杂数据类型就是对象)例如 函数,数组等等

二、为什么分为基本数据类型和引用数据类型

来个小实例看看二者的区别吧

let a=1
let b=a
a=2
console.log(b)

首先定义了两个基本类型的变量,并将a赋值给b,再把2赋值给a,再打印一下a,那么得到得结果是什么呢? 很显然是1。按照函数栈得执行上下文。我们分析一下为什么会出现这样的结果。

99DA396D-DA62-4D70-8068-663DF0AF8FE4.png

按照执行上下文作用域给a赋值为2,b为1后b的值并未改变,所以输出的结果为1是显而易见的。那么复杂数据类型也是这样的嘛?来看一下同样相似的代码。

let a= {
    age:18
}
let b=a
a.age=20
console.log(b.age)

如果基本数据类型和复杂数据类型是一样的没啥区别的话,那结果应该是18吧!!!!! ofcouse not 请看结果

image.png

最终的结果是20 显然基本数据类型和复杂数据类型是有很大的区别的,别急,我现在就告诉你这两者有什么区别,基本数据类型的大小是有限的,可以直接储存在函数栈里面,而复杂数据类型的数据可以无穷大,而函数栈的大小是固定的,不然设置为无穷大的话会严重影响性能,那么这么大的数据肯定就不能装在函数栈里面啦,所以v8引擎就给一个堆空间来存储复杂数据类型。

所以上述代码的执行是这样的,如图所示

2D1BB7D9-F92A-4F41-A854-491C210B0799.png

v8引擎会将a对象的值存入右边的堆当中,并有一个序号唯一对应,这个序号呢就天填在a对象的执行栈中(例:1010是a对象字面量中值得序号,所以在执行栈中a得值为1010),然后将a得值赋给b,是将a得序号赋给b,所以后面v8引擎按序号修改a中得值,b也按序号查找值当然也就发生了变化。总而言之,基本数据类型直接存储在执行栈中,而复杂数据类型有一个专门得堆空间存储,并有一个对应得序号。

复杂数据类型对象的创建 new 的作用

//对象的创建
var obj={}  //对象字面量

var obj2=new Object();//构造函数

//自定义构造函数
function Car(color){

    this.name='BMW'
    this.height=1400
    this.lang=4900
    this.weight=1000
    this.color=color
}
let car =new Car('green') //实例对象==this
let car2 =new Car('pink')
car.name='劳斯莱斯'
console.log(car)
console.log(car2)
//构造函数创建的多个对象都是独立的

创建对象有三种方法

  • 对象字面量
  • 构造函数
  • 自定义构造函数 当中有两种的创建对象都用了new这个方法,这个new执行了什么操作呢 这个new会创建一个空数组,然后将this对象填入空对象中,返回一个this对象。所以就能实现构造函数的实例化啦。这就是new的用法啦。

包装类 基本数据类型没有属性和方法?

是的没错,在js中明确规定基本数据类型没有属性和方法,属性和方法是对象专有的。那为什么有时候又感觉基本对象也可以用属性和方法呢? 让我们看一下例子

var num =123
num.a ='hello'
console.log(num.a);//undefinded

如上例所示 我们定义了一个数字类型的变量,然后给这个变量赋予了对象的属性,num.a='hello',我们知道这是对象的操作,那么直接打印num.a的话不就会报错嘛?

image.png 然而,它的结果是undefined,这不符合基本数据类型没有属性和方法。

我们再来看一个例子

var arr=[1,2,3,4]
arr.length
console.log(arr.length);

我们知道数组是对象 复杂数据类型,所以它可以用length方法

image.png

我们再看一个基本数据类型,字符串


var str ='abcd'
str.length
console.log(str.length);

image.png

我们看到基本数据类型也用了length方法,这是为什么呢?其实这就是包装类在起作用 所以,基本数据有属性和方法嘛。没有!!!!!明确规定,没有。 让我们来看一下到底怎么回事呢 实际上第一个例子,数字类型为什么变成了对象呢?那v8引擎执行了这个操作

 var num = new Number();
 num.a='hello'
 delete  num.a
 console.log(num.a);//类的包装

new创建了一个内部函数Number()给num,那num自然是一个对象呀,然后v8检测num的对象属性不是我们需要的,所以进行了删除操作,空对象为undefined,所以结果为undefined,不是基本数据类型有值,而是在v8里面创建了对象,也就是说这并不是属于基本数据类型而是对象,不违反基本数据类型没有属性和方法。

又例如上面字符串的例子其实在v8引擎中执行了类似于这样的代码

console.log(str.length)//4
new String('abcd').length

也就是说length方法也不是运用于字符串,而是new的对象的长度,这就是包装类。

包装类

通过上述的介绍,我们可以给包装类下一个定义,就是js会自动的将原始数据类型转化为对应的对象,以便调用对象的方法和属性。以上的例子都可以证明。

总结

js当中的基本数据类型没有属性和方法,是通过包装类的方法将基本数据类型转化为对象,从而可以用属性和方法。