此文章,来源于印客学院的资料,然后补充的。
此文档不一定涵盖了所有知识点,只是一个大概方向,仅供参考。
也算一个查漏补缺,诸君可以根据自己实际情况,自行衡量,看看哪里需要补充。
JavaScript 有哪些数据类型
,它们的区别?
JavaScript 共有八种数据类型,分别是 Undefined
、Null
、Boolean
、Number
、String
、Object
、Symbol
、BigInt
。
其中 Symbol
和 BigInt
是ES6 中新增
的数据类型:
- Symbol 代表创建后
独一无二且不可变
的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。 - BigInt 是一种
数字类型
的数据,它可以表示任意精度格式的整数, 使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了Number能够表示的安全整数范围。
这些数据可以分为 原始数据类型 和 引用数据类型 :
- 栈:原始数据类型(Undefined、Null、Boolean、Number、String)
- 堆:引用数据类型(对象、数组和函数)
两种类型的区别在于存储位置的不同:
- 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
- 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。
如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:
- 在数据结构中,栈中数据的存取方式为先进后出。
- 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。
在操作系统中,内存被分为栈区和堆区:
- 栈区内存 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
- 堆区内存 一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。
更多精彩内容,请微信搜索“前端爱好者
“, 戳我 查看 。
数据类型检测
的方式有哪些
在JavaScript中,有多种方式可以进行数据类型检测。以下是一些常见的方式:
使用typeof操作符:typeof是JavaScript的一元操作符,可以返回一个值的数据类型。
例如:
console.log(typeof "Hello World"); // 输出 "string"
console.log(typeof 42); // 输出 "number"
console.log(typeof true); // 输出 "boolean"
使用instanceof操作符:instanceof用于检查一个对象是否属于某个特定的类或构造函数的实例。
例如:
var arr = [];
console.log(arr instanceof Array); // 输出 true
var date = new Date();
console.log(date instanceof Date); // 输出 true
使用constructor属性:可以使用constructor属性来判断一个对象的构造函数。
例如:
var str = "Hello World";
console.log(str.constructor === String); // 输出 true
var num = 42;
console.log(num.constructor === Number); // 输出 true
使用Object.prototype.toString()方法:可以使用该方法来获取一个对象的内部属性[[Class]],从而判断其数据类型。
例如:
var obj = {};
console.log(Object.prototype.toString.call(obj)); // 输出 "[object Object]"
var func = function() {};
console.log(Object.prototype.toString.call(func)); // 输出 "[object Function]"
这些只是一些基本的方式,还有其他更复杂和详细的方式,如使用typeof和constructor结合判断、使用Array.isArray()方法判断数组等。
根据实际需求选择适合的方式进行数据类型检测。
null 和undefined 区别
在JavaScript中,null和undefined是两个特殊的值,用于表示缺失或无效的值。
null是一个表示空值的特殊关键字。它被认为是一个空对象指针,表示该变量没有指向任何有效的对象。当我们想要明确指示一个变量为空时,可以将其赋值为null。例如:
let myVariable = null;
console.log(myVariable); // 输出:null
undefined表示一个未定义的值,表示变量已经声明但尚未被赋值。当我们声明一个变量但没有给它赋初始值时,该变量的默认值为undefined。另外,如果我们访问一个不存在的属性或者调用一个不存在的函数,返回值也为undefined。例如:
let myVariable;
console.log(myVariable); // 输出:undefined
此外,null和undefined在使用方式上也有区别。当你希望表达一个变量有值但目前为空时,可以使用null。而undefined则通常表示未定义、缺失或错误的状态。
总结一下:
- null表示为空的值,是一个空对象指针。
- undefined表示未定义的值,表示变量已声明但未赋值,或者访问不存在的属性或函数时的返回值。
需要注意的是,在使用时要避免混淆null和undefined,根据具体情况正确选择使用。
intanceof 操作符的实现原理及实现
在 JavaScript 中,instanceof
是一个运算符,用于 检查对象是否属于指定类或其原型链上的某个类。它的实现原理可以描述如下:
instanceof
首先会判断左操作数(对象)是否有[[Prototype]]
属性,该属性指向对象的原型。- 接下来,它会判断右操作数(构造函数)是否具有
prototype
属性,该属性指向构造函数的原型对象。 - 如果左操作数的
[[Prototype]]
属性为null
,则返回false
。如果右操作数的prototype
属性为null
,则抛出TypeError
异常。 - 然后,
instanceof
将沿着左操作数的原型链逐级查找,直到找到右操作数的prototype
,或者到达原型链的尽头(null
)为止。 - 如果找到了匹配的原型对象,则返回
true
;否则返回false
。
这个过程是通过比较原型链中的对象是否与右操作数的 prototype
相等来完成的。
以下是一个简单的示例代码,演示如何使用 instanceof
运算符:
class Animal { }
class Dog extends Animal { }
const animal = new Dog();
if (animal instanceof Dog) {
console.log('animal 是 Dog 类型');
} else if (animal instanceof Animal) {
console.log('animal 是 Animal 类型');
} else {
console.log('animal 不是 Dog 类型也不是 Animal 类型');
}
在上述示例中,instanceof
运算符首先判断 animal
是否是 Dog
类的一个实例。由于 animal
是通过 new Dog()
创建的,所以它是 Dog
类的实例,输出 “animal 是 Dog 类型”。
如何获取安全的 undefined 值?
因为 undefined 是一个标识符,所以可以被当作变量来使用和赋值,但是这样会影响 undefined 的正常判断。
表达式 void 没有返回值,因此返回结果是 undefined。void 并不改变表达式的结果,只是让表达式不返回值。
因此可以用 void 0 来获得 undefined。
Object.is() 与比较操作符 “=”、“” 的区别?
在JavaScript中,Object.is() 方法和比较操作符 “=" 和 "” 在比较值时有一些区别。
- Strict Equality (严格相等,“===”):
- 使用 “===” 进行比较时,会先判断两个值的数据类型是否相同,如果不同则直接返回 false。
- 如果两个值的数据类型相同,再进一步比较它们的值。
- 使用 “===” 比较时,对于数字、字符串、布尔值等基本类型的值,只有在值相同的情况下才会返回 true。
- 对于引用类型的值(如对象、数组等),比较的是它们在内存中的引用地址,只有当两个引用指向同一个对象时才会返回 true。
示例:
console.log(42 === 42); // 输出 true
console.log("hello" === "hello"); // 输出 true
console.log(true === true); // 输出 true
var obj1 = {};
var obj2 = obj1;
console.log(obj1 === obj2); // 输出 true
- Abstract Equality (抽象相等,“==”):
- 使用 “==” 进行比较时,会进行类型转换,尝试将两个值转换为相同的类型,然后再进行比较。
- 在进行类型转换时,会根据一些规则进行隐式类型转换,例如将字符串转换为数字。
- 如果两个值的类型相同,则和使用 “===” 比较相同。
- 如果两个值的类型不同,会尝试将它们转换为相同的类型进行比较。具体转换规则相对复杂,不太直观。
示例:
console.log(42 == "42"); // 输出 true,进行了类型转换后相等
console.log(null == undefined); // 输出 true,特殊规则,被认为相等
var obj = {};
console.log(obj == "[object Object]"); // 输出 true,对象和字符串进行了隐式类型转换
- Object.is() 方法:
- Object.is() 方法用于比较两个值是否严格相等,类似于 “===” 操作符。
- 与 “===” 不同的是,Object.is() 方法对于一些特殊情况的处理更加准确。
- 特殊情况包括处理 NaN 和处理 +0/-0 的区别。
示例:
console.log(Object.is(NaN, NaN)); // 输出 true,对于 NaN 的判断更准确
console.log(Object.is(+0, -0)); // 输出 false,对于 +0/-0 的判断更准确
综上所述,Object.is() 方法在比较值时更准确,特别是对于 NaN 和 +0/-0 的处理。在一般情况下,推荐使用 “===” 进行严格相等比较。
什么是 JavaScript 中的包装类型?
JavaScript中的包装类型(Wrapper Types)是指用于将原始数据类型(Primitive Data Type)包装成对象的特殊对象。
在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象,如:
在访问’abc’.length 时, JavaScript 将’abc’ 在后台转换成String(‘abc’),然后再访问其length 属性。
JavaScript 也可以使用Object 函数显式地将基本类型转换为包装类型:
var a = 'abc'
Object(a) // String {"abc"}
也可以使用valueOf 方法将包装类型倒转成基本类型:
看看如下代码会打印出什么:
答案是什么都不会打印,因为虽然包裹的基本类型是 false,但是false 被包裹成包装类型后就成了对象,所以其非值为 false,所以循环体中的内容不会运行。