原生JavaScript灵魂拷问,你能答上多少(一)2

简介: 原生JavaScript灵魂拷问,你能答上多少(一)2

10.你能理清类型转换吗?


首先需要知道:在JavaScript中,只有三种类型的转换


  • 转换为Number类型: Number() / parseFloat() / parseInt()
  • 转化为String类型: String() / toString()
  • 转化为Boolean类型: Boolean()


因此遇到类型转换问题,只需要弄清楚在什么场景之下转换成那种类型即可。


转换为boolean


  • 显式:Boolean 方法可以显式将值转换为布尔类型
  • 隐式:通常在逻辑判断或者有逻辑运算符时触发(|| && !


Boolean(1)   // 显式类型转换
if (1) {}    // 逻辑判断类型触发隐式转换
!!1          // 逻辑运算符触发隐式转换
1 || 'hello' // 逻辑运算符触发隐式转换
复制代码


boolean 类型只有 truefalse 两种值。


除值 0,-0,null,NaN,undefined,或空字符串("")false 外,其余全为 true


转化为string


  • 显式:String 方法可以显式将值转换为字符串
  • 隐式:+ 运算符有一侧操作数为 string 类型时


转化为 string 类型的本质:需要转换为string的部分调用自身的toString方法


(null/undefined返回字符串格式的null和undefined)


当被转换值为对象时,相当于执行 ToPrimitive(input, 'hint String')


String([1,2,3]) // 1,2,3
String({x:1}) // [object Object]
1 + '1' // 11
1 + {} // 1[object Object]
复制代码


转化为number


  • 显式:Number 方法可以显式将值转化为数字类型


Number 的具体规则,ES5 规范中给了一个对应的结果表


类型 结果
undefined NaN
null +0
Boolean NaN
undefined 参数为true返回1;false返回+0
Number 返回与之相等的值
String 有些复杂,举例说明
Object 先执行ToPrimitive方法,在执行Number类型转换


  1. String: 空字符串返回 0,出现任何一个非有效数字字符,返回 NaN


console.log(Number("1 3")) // NaN
console.log(Number("abc")) // NaN
console.log(Number("1a")) // NaN
console.log(Number("0x11")) // 17
console.log(Number("123")) // 123
console.log(Number("-123")) // -123
console.log(Number("1.2")) // 1.2
复制代码


  • 隐式:number的隐式类型转换比较复杂,对需要隐式转换的部分执行 Number


  • 比较操作(<, >, <=, >=)
  • 按位操作(| & ^ ~)
  • 算数操作(+ - * / %) 注意:+的操作数存在字符串时,为string转换
  • 一元 +- 操作


11.== 的隐式转换规则


  1. ==: 只需要值相等,无需类型相等;null, undefined== 下互相等且自身等
  2. == 的转换规则:


被比较数B
Number String Boolean Object
比较数A
Number A == B A == ToNumber(B) A == ToNumber(B) A == ToPrimitive(B)
String ToNumber(A) == B A == B ToNumber(A) == ToNumber(B) ToPrimitive(B) == A
Boolean ToNumber(A) == B ToNumber(A) == ToNumber(B) ToNumber(A) == ToNumber(B) ToNumber(A) == ToPrimitive(B)
Object ToPrimitive(A) == B ToPrimitive(A) == B ToPrimitive(A) == ToPrimitive(B) A === B


在上面的表格中,ToNumber(A) 尝试在比较前将参数 A 转换为数字。


ToPrimitive(A) 将参数 A 转换为原始值( Primitive )。


12.1 + {}{} + 1的输出结果分别是什么?


通过上面的学习,当对象与其他元素相加时,对象会调用 toPrimitive 转化为原始值:


  1. 执行 toPrimitive,未传入 PreferredTypemethodNames[valueOf, toString]
  2. 执行 ({}).valueOf,返回对象本身 {},不是原始值
  3. 继续执行 ({}).toString(),返回 "[object Object]",返回结果为原始值,转换结束


此时 1 + {},右侧为 string 类型,将 1 进行 ToString() 转化为 "1" ,最后字符串连接,结果为 "1[object Object]"


注意{} + 1 输出的结果会和 1 + {} 一样吗?


{}JavaScript 中,不止可以作为对象定义,也可以作为代码块的定义。js 引擎会把 {} + 1 解析成1个代码块和1个+1,最终输出结果为 1


答案


1[object Object]
1
复制代码


13.[]与{}的相加的结果是多少?


[] + {}


数组是特殊的对象,需要调用 toPrimitive,转换为原始值


  • 执行 toPrimitive,未传入 PreferredTypemethodNames[valueOf, toString]
  • 执行 [].valueOf,返回数组本身
  • 执行 [].toString,返回空字符串 ''


空对象不做赘述。


答案


"[object Object]"
复制代码


[] + []


类似 1 两个空数组都执行 toPrimitive,返回两个空字符串。


答案

""
复制代码


{} + []


类似于 {} + 1{} + [] 相当于 {}; + [],一元 + 强制将 "" 隐式转换为0,最终结果为0


答案

0
复制代码


{} + {}


对于这个题,我先公布一下答案,之后说一下我的疑问。


答案


[object Object][object Object]
复制代码


疑问


为什么 JavaScript 引擎没有将前面的 {} 解释成代码块?


友情提示:由于 {} 可以解释为代码块的形式,有些需要注意的地方,举个栗子:

  • 空对象调用方法时:{}.toString() 会报错
  • 箭头函数返回对象时:let getTempItem = id => { id: id, name: "Temp" } 会报错


14.你能灵活运用 parseInt 与 parseFloat 吗


  1. parseInt:从数字类开始看,看到非数字类为止,返回原来的数。(小数点也属于非有效数字)


parseInt('123x') -> 123
parseInt('-023x') -> -23
parseInt('1.1') -> 1
parseInt('-abc') -> NaN
parseInt('x123') -> NaN
复制代码


  1. parseInt(string, radix) 还有第二个参数 radix 表示要解析数字的基数,取值为 2~36 (默认值为10)
  2. parseFloatparseInt 类似,只不过它返回浮点数。从数字类开始看,看到除了第一个点以外的非数字类为截止,返回前面的数。


网红题:['1','2','3'].map(parseInt)


这个网红题考察的就是 parseInt 有两个参数。 map 传入的函数可执行三个参数:


// ele   遍历的元素
// index 遍历的元素索引
// arr   数组
arr.map(function(ele, index, arr){})
复制代码


['1','2','3'].map(parseInt)相当于执行了以下三次过程:


parseInt('1', 0, ['1','2','3'])
parseInt('2', 1, ['1','2','3'])
parseInt('3', 2, ['1','2','3'])
复制代码


  • parseInt('1', 0, ['1','2','3']): radix为0时,默认取10,最后返回1
  • parseInt('2', 1, ['1','2','3']): radix取值为2~36,返回NaN
  • parseInt('3', 2, ['1','2','3']): radix取值为2,二进制只包括0,1,返回NaN


15.如何让 if(a == 1 && a == 2) 条件成立?


valueOf 的应用


var a = {
    value: 0,
    valueOf: function() {
        this.value++;
        return this.value;
    }
};
console.log(a == 1 && a == 2); //true


相关文章
|
2月前
|
JavaScript 前端开发 安全
安全开发-JS应用&原生开发&JQuery库&Ajax技术&加密编码库&断点调试&逆向分析&元素属性操作
安全开发-JS应用&原生开发&JQuery库&Ajax技术&加密编码库&断点调试&逆向分析&元素属性操作
|
2月前
|
JavaScript
原生JS实现全选、全不选
原生JS实现全选、全不选
|
1月前
|
JavaScript
js 一键复制到剪贴板(原生js实现)
js 一键复制到剪贴板(原生js实现)
14 0
|
2月前
|
前端开发 JavaScript 容器
程序技术好文:纯原生javascript下拉框表单美化实例教程
程序技术好文:纯原生javascript下拉框表单美化实例教程
23 0
|
2月前
|
移动开发 JavaScript 前端开发
原生js如何获取dom元素的自定义属性
原生js如何获取dom元素的自定义属性
54 0
|
2月前
|
JavaScript 前端开发
原生JS如何查询元素属性
原生JS如何查询元素属性
24 0
|
2月前
|
JavaScript 开发者 前端开发
浅谈Vue.js与原生开发
Vue.js 是一款流行的前端框架,以其独特的模板语法简化了动态视图创建,通过指令和表达式便捷处理数据。与原生开发相比,Vue.js 提供了Vue Router进行高效路由管理,Vuex进行状态集中管理,以及丰富的生态系统和工具链如Vue CLI。Vue组件化开发、响应式数据绑定和单文件组件提高了代码复用和可维护性,但原生开发在性能和直接操作DOM方面可能更具优势。
|
设计模式 前端开发 JavaScript
100行代码让您学会JavaScript原生的Proxy设计模式
100行代码让您学会JavaScript原生的Proxy设计模式
124 0
100行代码让您学会JavaScript原生的Proxy设计模式
|
1月前
|
JavaScript Java 测试技术
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
基于springboot+vue.js+uniapp的客户关系管理系统附带文章源码部署视频讲解等
59 2

热门文章

最新文章