JavaScript 数据类型
面试中经常被问到 JavaScript 数据类型都有哪些?有些时候面试者因为紧张连这最基础的题目都回答不出来或者回答不够全面,下面我们来具体了解下 JavaScript 数据类型吧!
首先,需要答出 JavaScript 数据类型分为基本类型(简单类型)和引用类型(复杂类型)两种,分别是:
基本类型
string (字符串)
boolean (布尔)
number (数字)
undefined (undefined)
null (null)
symbol (代表创建后独一无二且不可变的数据类型)
引用类型
Object (对象)
Array (数组)
Function (函数)
这个时候面试官可能又会接着问:那你知道这两种数据类型有什么区别吗?
存放位置不同
基本类型的变量会保存在栈内存中,如果在一个函数中声明一个基本类型的变量,这个变量在函数执行结束后会自动销毁。 而引用类型的变量名会保存在栈内存中,但是变量值会存储在堆内存中,引用类型的变量不会自动销毁,当没有引用变量引用它时,系统的垃圾回收机制会回收它。
赋值不同
基本类型的赋值相当于深拷贝,赋值后相当于又开辟了一个内存空间,如下所示:
let a = 100;
let b = a;
b = 101;
console.log(a, b); // 100 101
copy
可以看出当 a 的值改变时并不影响 b 的值。
而引用类型的赋值是浅拷贝,当我们对对象进行操作时,其实操作的只是对象的引用,如下所示:
let obj = {
name: “蓝桥”,
};
let obj2 = obj;
obj2.name = “蓝桥云课”;
console.log(obj.name, obj2.name); // 蓝桥云课 蓝桥云课
copy
可以看出,我们把 obj 的值赋值给 obj2,当 obj2 的值改变时,obj 的值也被改变。
这个时候面试官可能又接着问:那如何实现一个对象的深拷贝呢?
最简单的方式就是使用 JSON.stringify 和 JSON.parse 这组 API,如下所示:
JSON.stringify() 方法用于将 JavaScript 值转换为 JSON 字符串;JSON.parse() 方法将 JSON 字符串转化为 JavaScript 对象
let obj = {
name: “蓝桥”,
};
let obj2 = JSON.parse(JSON.stringify(obj));
obj2.name = “蓝桥云课”;
console.log(obj.name, obj2.name); // 蓝桥 蓝桥云课
copy
但是这种方式有些问题,当 obj 里面有函数或者 undefined 就会失效,如下所示:
let obj = {
fn: function () {
console.log(“我是蓝桥”);
},
name: undefined,
};
let obj2 = JSON.parse(JSON.stringify(obj));
console.log(obj2); //{}
copy
所以万全之策还是要用递归,如下所示:
function deep(obj) {
let oo = {};
for (const key in obj) {
if (typeof obj[key] === “object”) {
oo[key] = deep(obj[key]);
} else {
oo[key] = obj[key];
}
}
return oo;
}
copy
上述代码的原理就是递归遍历对象的每个属性,分别赋值到一个新对象去。
现在再回头来看看我们的第一个问题,一个简简单单的数据类型就能牵扯到这么多知识点。有经验的面试官会从一道题目上层层递进的提问,来区分出不同面试者的水平。
原型及原型链
面试中经常问道,你知道什么是原型吗?或者你对原型链是如何理解的?说实话,这道面试题挺难的,要想彻底搞清楚原型及原型链,需要我们下很大功夫去理解,所以以下知识点建议大家反复阅读,逐步消化。
我们所有的知识点都来自于以下理论:
每个函数都有 prototype 属性,每一个对象都有 proto 属性(这个属性称之为原型),在我们执行 new 的时候,对象的 proto 指向这个构造函数的 prototype。
首先,每个函数都有个 prototype 属性,这个属性指向函数的原型对象,同时 prototype 里面有个 constructor 属性回指到该函数。如下所示:
function Demo() {}
Demo.prototype.constructor === Demo; // true
copy
Demo.prototype 结构如下所示:
图片描述
现在我们使用 new 操作符来创建一个实例对象,如下所示:
当使用 new 操作符后,Demo 就变成了构造函数
function Demo() {}
const d = new Demo(); // d 就是创建出来的实例对象
copy
d 既然是对象,自然有 proto(原型) ,同时指向构造函数 Demo 的 prototype,如下所示:
function Demo() {}
const d = new Demo();
d.proto === Demo.prototype; // true
copy
当我们访问一个对象的属性时,程序会先去这个对象里面查找,如果没有找到会去这个对象的原型上查找,如下所示:
function Demo() {
this.name = “蓝桥”;
}
Demo.prototype.say = function () {
console.log(“我是”, this.name);
};
const d &