冯站长之家,张掖市网站建设,dnf免做卡怎么领取网站,中山网官网✨✨✨目录
1.JavaScript有哪些数据类型及区别#xff1f;
2.数据类型检测的方式有哪些#xff1f;
3.null与undefined的区别#xff1f;
4.instanceof操作符的实现原理及实现#xff1f;
5.为什么0.10.2!0.3#xff0c;如何让其相等#xff1f;
6.isNaN和Number.i…✨✨✨目录
1.JavaScript有哪些数据类型及区别
2.数据类型检测的方式有哪些
3.null与undefined的区别
4.instanceof操作符的实现原理及实现
5.为什么0.10.2!0.3如何让其相等
6.isNaN和Number.isNaN函数的区别
7.JavaScript 中的类型转换机制
8.Object.is()与比较操作符、的区别 9.什么是JavaScript中的包装类型
10.为什么会有BigInt的提案
11.object.assign和扩展运算法是深拷贝还是浅拷贝深浅拷贝两者区别
12.如何判断一个对象是空对象
13.const、let、var的区别
14.如果new一个箭头函数会怎么样
15.new操作符的实现流程 1.JavaScript有哪些数据类型及区别
JavaScript 中的数据类型主要分为两大类基本数据类型和引用数据类型。
基本数据类型Undefined、Null、Boolean、Number、String、Symbol、BigInt
引用数据类型Object、Array、Function、Date、RegExp
两种数据类型的区别栈——原始数据类型堆——引用数据类型区别在于存储位置的不同。
原始数据类型直接存储在栈中的简单数据段占据空间小、大小固定属于被频繁使用数据所以放入栈中存储引用数据类型存储在堆中的对象占据空间大大小不固定。
2.数据类型检测的方式有哪些
typeof、instanceof、Object.prototype.toString.call()、Array.isArray()、constructor
typeof用于检测基本数据类型如 number、string、boolean、undefined、symbol、bigint和函数返回 function。但对 null 返回 object对数组和对象均返回 object存在局限性。
instanceof 用于检测对象是否为某个构造函数的实例适用于引用类型如 Array、Date、自定义类等。
Object.prototype.toString.call()通过调用对象的 toString 方法并解析返回的字符串可以精确检测所有类型。如Object.prototype.toString.call(null); // [object Null] Object.prototype.toString.call([]); // [object Array]
Array.isArray()专门用于检测数组。
constructor有两个作用一是判断数据的类型二是对象实例通过constructor对象访问它的构造函数。如果创建一个对象来改变它的原型constructor就不能用来判断数据类型了。
3.null与undefined的区别
null表示一个显式赋值的空值通常用于表示“无对象”或“无值”。
undefined表示一个未初始化的变量或未赋值的属性通常由 JavaScript 引擎自动赋予。
特性nullundefined语义显式空值人为设定未初始化或未定义typeof 结果objectundefined是否可显式赋值是是但通常由引擎自动赋予严格相等性null ! undefinedundefined ! null常见使用场景清空变量、函数参数默认值未初始化变量、函数无返回值、不存在的属性 console.log(null undefined); // true console.log(null undefined); // false 4.instanceof操作符的实现原理及实现
instanceof 操作符是 JavaScript 中用于检测对象是否为某个构造函数或其原型链上的构造函数的实例的运算符。它的实现原理基于原型链继承机制通过检查对象的原型链中是否存在构造函数的 prototype 属性来实现类型判断。
instanceof 的实现原理 instanceof 会从对象的原型链__proto__开始逐级向上查找直到找到匹配的 prototype 或到达原型链的末端null。如果对象的原型链中存在构造函数的 prototype则返回 true否则返回 false。对于 obj instanceof Constructor其逻辑等价于
function isInstanceOf(obj, Constructor) {let prototype Constructor.prototype;let currentProto Object.getPrototypeOf(obj);while (currentProto ! null) {if (currentProto prototype) {return true;}currentProto Object.getPrototypeOf(currentProto);}return false;
}
5.为什么0.10.2!0.3如何让其相等
在 JavaScript 中0.1 0.2 ! 0.3 的问题源于浮点数在计算机中的二进制表示方式导致的精度丢失。十进制的小数如 0.1、0.2在二进制中可能是无限循环小数导致存储时被截断产生精度误差。例如0.1 的二进制表示为 0.0001100110011...无限循环。0.2 的二进制表示为 0.001100110011...无限循环。当 0.1 和 0.2 相加时它们的二进制表示误差会累积导致结果略大于 0.3。
解决方法通过 toFixed() 或数学运算将结果四舍五入到指定小数位将小数转换为整数进行计算定义一个极小的误差范围如 Number.EPSILON判断差值是否在范围内使用第三方库。
6.isNaN和Number.isNaN函数的区别
isNaN 是全局函数用于检测一个值是否“不是数字”即无法转换为有效数字存在隐式类型转换。 console.log(isNaN(hello)); // truehello 无法转换为数字 console.log(isNaN(123)); // false123 可以转换为数字 123 console.log(isNaN(true)); // falsetrue 转换为数字 1 console.log(isNaN(NaN)); // true直接是 NaN Number.isNaN 是 Number 对象的静态方法用于严格检测一个值是否为 NaN。 console.log(Number.isNaN(hello)); // false字符串不是 NaN console.log(Number.isNaN(123)); // false字符串不是 NaN console.log(Number.isNaN(true)); // false布尔值不是 NaN console.log(Number.isNaN(NaN)); // true直接是 NaN 特性isNaNNumber.isNaN隐式类型转换是尝试转换为数字否直接比较适用场景检测值是否“无法转换为数字”严格检测值是否为 NaN非数字但可转换的值返回 false如 、 、[]返回 false严格匹配 NaN直接传递 NaN返回 true返回 true
7.JavaScript 中的类型转换机制
JavaScript 类型转换分为两类显式类型转换-开发者通过函数或方法主动将一种类型转换为另一种类型如 Number()、String()、Boolean()隐式类型转换-JavaScript 引擎在特定操作如算术运算、比较、逻辑判断中自动将一种类型转换为另一种类型。 显式类型转换
1转换为字符串String
String(value)
value.toString()注意null 和 undefined 没有 toString() 方法 console.log(String(123)); // 123 console.log(String(true)); // true console.log(String(null)); // null console.log(String(undefined));// undefined console.log((123).toString()); // 123数字调用 toString 2转换为数字Number
Number(value)
parseInt(value, radix)解析整数
parseFloat(value)解析浮点数
一元加号运算符 value
规则
原始类型转换为数字的结果字符串解析为数字如 123 → 123无法解析时为 NaN布尔值true → 1false → 0null0undefinedNaN对象/数组调用 valueOf() 或 toString() 后再转换 console.log(Number(123)); // 123 console.log(Number(123abc)); // NaN console.log(Number(true)); // 1 console.log(Number(null)); // 0 console.log(Number(undefined));// NaN console.log(Number([1, 2])); // NaN调用 valueOf() 或 toString() 后再转换→ 1,2 → NaN console.log([]); // 0空数组调用 toString() → → 0 3转换为布尔Boolean
Boolean(value)
双感叹号 !!value
规则假值列表false、0、空字符串、null、undefined、NaN 会转换为 false其他值均为 true。 console.log(Boolean(0)); // false console.log(Boolean()); // false console.log(Boolean(null)); // false console.log(Boolean([])); // true空数组是对象非假值 console.log(Boolean({})); // true空对象是非假值 console.log(!!hello); // true 隐式类型转换
1算术运算中的隐式转换
加法运算符 如果任意操作数是字符串则进行字符串拼接。否则尝试将操作数转换为数字进行加法。
其他运算符-、*、/、%总是将操作数转换为数字。 console.log(123 456); // 123456字符串拼接 console.log(123 true); // 124true → 1 console.log(123 - 456); // -333字符串 → 数字 console.log(123 - true); // 122true → 1 console.log([] 1); // 1空数组 → → 1 console.log({} 1); // [object Object]1对象 → [object Object] 2 比较运算符中的隐式转换
宽松相等 如果类型相同直接比较。如果类型不同尝试转换为相同类型后再比较。 console.log(0 false); // truefalse → 0 console.log( false); // true → 0false → 0 console.log(null undefined); // true特殊规则 console.log(123 123); // true字符串 → 数字 console.log([] false); // true[] → → 0false → 0 console.log({} {}); // false对象比较引用 严格相等 不进行类型转换类型或值不同则返回 false。
推荐始终使用 避免隐式转换问题。
3逻辑运算符中的隐式转换 和 ||操作数会被转换为布尔值但返回的是原始值非布尔值。
||逻辑或和逻辑与操作符在JavaScript中的返回值机制如下
逻辑或||操作符从左到右依次检查操作数。如果第一个操作数为真值Truthy则直接返回第一个操作数如果第一个操作数为假值Falsy则返回第二个操作数。不会强制转换为布尔值直接返回原始值。
常见用途用于设置默认值、避免访问未定义的属性等。
逻辑与操作符从左到右依次检查操作数。如果第一个操作数为假值则直接返回第一个操作数如果第一个操作数为真值则返回第二个操作数。不会强制转换为布尔值直接返回原始值。 console.log(0 hello); // 00 是假值直接返回 console.log(hello 0); // 0hello 是真值返回第二个操作数 console.log(null || world); // worldnull 是假值返回第二个操作数 4条件语句中的隐式转换
if、while、for 等语句的条件表达式会被转换为布尔值。 if () { console.log(不会执行); // 空字符串是假值 } if ([]) { console.log(会执行); // 空数组是真值 } 8.Object.is()与比较操作符、的区别
Object.is() 是 JavaScript 中用于严格比较两个值是否相等的方法与 运算符的主要区别在于对有符号零0/-0和 NaN 的处理其中 Object.is(0, -0) 返回 falseObject.is(NaN, NaN) 返回 true。
严格相等判断Object.is() 接收两个参数返回布尔值仅在以下情况返回 true
两个值类型相同且值相等包括对象引用比较
两个值均为 undefined 或 null
两个值均为 NaN唯一能正确识别 NaN 相等性的方法
两个值分别为 0 和 -0 时返回 false区别于
与其他比较运算符的差异对比
比较方式类型转换NaN NaN0 -0宽松相等有falsetrue严格相等无falsetrueObject.is()无truefalse
应用场景分析
精确值匹配在需要严格区分 0 和 -0 的科学计算或图形处理中替代
NaN 检测替代 x x 的 NaN 检查方式因 Object.is(x, NaN) 更直观
React 性能优化用于 shouldComponentUpdate 生命周期方法中判断 props/state是否变化 9.什么是JavaScript中的包装类型
概念JavaScript中的包装类型是指为了便于操作基本数据类型如String、Number、Boolean等JavaScript在后台将这些基本类型的值临时包装成对象从而允许调用这些对象的方法和属性。
自动装箱当读取一个基本类型的值时JavaScript会自动将其包装成一个对象。例如当访问字符串hello.length时JavaScript会在后台将hello包装成一个String对象然后访问其length属性。
显式创建可以使用Object()函数显式地将基本类型转换为包装类型。例如Object(hello)会将hello显式地转换为String对象。
拆箱当操作完成后这些对象会被拆箱回基本类型。例如通过valueOf()方法可以将包装类型转换回基本类型。
生命周期和内存管理基本包装类型的对象在执行完一行代码后会被立即销毁这意味着在运行时为基本包装类型值添加属性和方法是无效的。这是因为它们的生命周期非常短暂仅在代码执行的一瞬间存在。
10.为什么会有BigInt的提案
BigInt的提案主要是由于JavaScript中Number类型在处理大数时的精度问题。
JavaScript中的Number类型有一个最大安全整数限制即Number.MAX_SAFE_INTEGER其值为9007199254740991。在这个范围内计算结果不会出现精度丢失但一旦超过这个范围就会出现计算不准确的情况。这在需要进行大数计算时不得不依靠一些第三方库来解决因此官方提出了BigInt来解决此问题。
11.object.assign和扩展运算法是深拷贝还是浅拷贝深浅拷贝两者区别
Object.assign和扩展运算符都是浅拷贝工具而不是深拷贝工具。
Object.assign(target, ...sources)将一个或多个源对象的属性复制到目标对象中。会直接修改目标对象覆盖同名属性且只复制对象的可枚举属性嵌套对象是引用复制。 const target {a: 1};
const source {b: 2, c: 3};
const result Object.assign(target, source);
console.log(result); // { a: 1, b: 2, c: 3 }
console.log(target); // { a: 1, b: 2, c: 3 }扩展运算符{...source}将一个对象的属性展开到另一个对象中。同样只复制对象的可枚举属性嵌套对象是引用复制。 const obj1 {a: 1, b: {c: 2}};
const obj2 {...obj1};
obj2.b.c 3;
console.log(obj1.b.c); // 3浅拷贝和深拷贝的定义及区别
浅拷贝只复制对象的第一层属性嵌套对象是引用复制。修改嵌套对象的属性会影响原对象。
深拷贝递归复制对象及其所有嵌套对象确保每个层级的内容都被独立复制不再共享引用地址。深拷贝可以使用JSON.parse(JSON.stringify())或第三方库如Lodash的_.cloneDeep()实现。
12.如何判断一个对象是空对象
Object.keys(obj).length0仅检查可枚举字符串属性忽略Symbol属性。
JSON.stringify(obj) {}会忽略undefined和函数类型属性存在误判风险。
13.const、let、var的区别
1块级作用域 let 和 const具有块级作用域由 {} 包括。这解决了ES5中内层变量可能覆盖外层变量和循环变量泄露为全局变量的问题。 var不具备块级作用域只有函数作用域或全局作用域。
2变量提升var特有
let 和 const不存在变量提升必须在声明后才能使用否则报错。var存在变量提升即变量可以在声明之前使用但值为 undefined。
3全局属性
let 和 const不会将声明的全局变量添加到全局对象的属性上。var声明的全局变量会成为全局对象浏览器中是 windowNode中是 global的属性
4重复声明
var允许在同一作用域内重复声明变量后声明的会覆盖前面声明的。let 和 const不允许在同一作用域内重复声明变量。
5暂时性死区let、const特有
let 和 const在声明前使用会报错因为这段时间称为暂时性死区。var不存在暂时性死区。
6初始值设置
var 和 let可以不设置初始值。const必须设置初始值。
7指针指向
let、var创建的变量可以重新赋值即可以更改指针指向。const声明的变量不允许改变指针的指向但如果是对象或数组可以修改其内部属性或元素。
总结
区别letconstvar有无块级作用域√√×有无变量提升××√能否添加全局属性××√能否重复声明变量××√有无暂时性死区√√×必须设置初始值×√×能否改变指针指向√×√
14.如果new一个箭头函数会怎么样
箭头函数是ES6中的提出来的它没有prototype也没有自己的this指向更不可以使用arguments参数所以不能New一个箭头函数。
new操作符的实现步骤如下
1创建一个空的简单JavaScript对象即{}
2为步骤1新创建的对象添加属性__proto__将该属性链接至构造函数的原型对象
3将步骤1新创建的对象作为this的上下文
4如果该函数没有返回对象则返回this。
所以上面的第二、三步箭头函数都是没有办法执行的。
15.new操作符的实现流程
在JavaScript中new操作符用于创建一个给定构造函数的实例对象。 创建一个新的对象obj 将对象与构造函数通过原型链连接起来 将构造函数中的this绑定到新建的对象obj上 根据构造函数中返回值如果是值类型返回创建的对象如果是引用类型就返回这个引用类型对象。
function Test(name) {this.name namereturn 1
}
const t new Test(xxx)
console.log(t.name) // xxxfunction Test1(name) {this.name nameconsole.log(this) // Test { name: xxx }return { age: 26 }
}
const t1 new Test1(xxx)
console.log(t1) // { age: 26 }
console.log(t1.name) // undefined
function Person(name, age){this.name name;this.age age;
}
Person.prototype.sayName function () {console.log(this.name)
}
const person1 new Person(Tom, 20)
console.log(person1) // Person {name: Tom, age: 20}
person1.sayName() // Tom
持续更新中......
若文章对你有帮助点赞❤️、收藏⭐加关注➕吧