JS相关
基础类型有哪些?
基本类型有七种
null
undefined
boolean
number
string
symbol
(较新标准)BigInt
(新标准)
NaN
也属于 number
类型,并且 NaN
不等于自身;
基础类型的特性是什么?
- 基本类型的值是保存在
栈内存
中的简单数据段 - 基础类型是
不可变的
- 即不能强行修改:
Array.prototype.sort.call('abc');
(会报错)
- 即不能强行修改:
- 基础类型上没有
__proto__
没有属性
怎么检测基础类型?
- 检测基础类型可以用
typeof
,但是typeof null === 'object'
null
是基础类型,不是 Object- 由于null的历史遗留问题(前三位为000),所以使用
typeof
检测null会产生BUG
// 借鉴 Vue 源码的 object 检测方法 function isObject (obj: any): Boolean { return obj !== null && typeof obj === 'object' } 复制代码
- 通过
Object.prototype.toString.call
(万能方法)- 检测
[[class]]
- 在不覆盖 toString 方法前提下,任何一个对象调用 Object 原生的 toString 方法都会返回
[object type]
// 借鉴 Vue 源码的检测方法 let _toString = Object.prototype.toString; function toRawType (value: any): String { // 获取 从第九个到倒数第二个 字符 // 比如 [object String] 获取 String return _toString.call(value).slice(8, -1) }
- 检测
基础类型是如何转换的?
- 基本类型转换时,首先会调用
valueOf
,然后调用toString
。(这两个方法可以被重写) -
在四则运算中,除了
+
其他操作都会以数字进行计算,如果是+
运算,如果不是所有字面量都是number
(都是number就是数字的加法咯),那么会转换为字符串(toString
)进行拼接 -
那么怎么解决 JS 的精确度问题?
- 目前主流的解决方案是
先乘再除
- 比如精确到小数点后2位
- 先把需要计算的数字都 乘1000
- 计算完成后再把结果 除1000
- 使用新基础类型
BigInt
(兼容性很差)
- 目前主流的解决方案是
JS的"真"值有哪些?
JS中除了 "假" 值以外就是 "真" 值。
"假"值包括 7 个
undefined
null
false
NaN
''
0
-0
在条件判断的隐式转换中:"假" 值会转换为 false
,"真" 值会转换为 true
;
怎么检测引用类型?
- 通过
Object.prototype.toString.call
检测[[class]]
- 通过
instanceof
判断引用类型 - 通过
constructor
判断引用类型(constructor
是可写的,慎用)
instanceof 的原理是什么?
instanceof
内部机制是通过判断对象的原型链中是不是能找到对应的的prototype
[] == ![] 结果是什么?
PS: 感谢 @沉末_ 的补充
类型转换都是先 valueOf
再 toString
;
右边
- 由于
!
优先级比==
高,先执行!
![]
得到 false- 进行 相等性判断
false
转化为数字0
左边
- 执行
[].valueOf()
原始值 还是 [] - 执行 [].toString() 得到 ''
''
转化为数字0
所以:0 == 0
,答案是 true
如何让 (a == 1 && a == 2)条件成立?
依然是类型转换逻辑:基础类型通过 valueOf
进行隐式转换
更改 valueOf
方法就可以实现
let a = {
value: 0,
valueOf: function() {
this.value++;
return this.value;
}
};
console.log(a == 1 && a == 2);
7. IE和DOM事件流的区别
1.执行顺序不一样
事件流的区别 IE采用冒泡型事件 Netscape使用捕获型事件 DOM使用先捕获后冒泡型事件 示例: <body> <div> <button>点击这里</button> </div> </body> 冒泡型事件模型: button->div->body (IE事件流) 捕获型事件模型: body->div->button (Netscape事件流) DOM事件模型: body->div->button->button->div->body (先捕获后冒泡)
2.参数不一样 低版本ie没有回调函数,只能进行冒泡
3.第一个参数是否加"on",低版本IE不支持addEventListener(),支持attachEvent,第一个参数需要加"on"
element.addEventListener('click', observer, useCapture); addEventListener方法接受三个参数。第一个参数是事件名称,值得注意的是,这里事件名称与IE 的不同,事件名称是没’on’开头的;第二个参数observer是回调处理函数;第三个参数注明该处理回调 函数是在事件传递过程中的捕获阶段被调用还是冒泡阶段被调用
2.事件侦听函数的区别 IE使用: [Object].attachEvent("name_of_event_handler", fnHandler); //绑定函数 [Object].detachEvent("name_of_event_handler", fnHandler); //移除绑定 DOM使用: [Object].addEventListener("name_of_event", fnHandler, bCapture); //绑定函数 [Object].removeEventListener("name_of_event", fnHandler, bCapture); //移除绑定 bCapture参数用于设置事件绑定的阶段,true为捕获阶段,false为冒泡阶段。
4.this指向问题,IE指向windows,不指向触发的函数
element.attachEvent('onclick', observer); attachEvent接受两个参数。第一个参数是事件名称,第二个参数observer是回调处理函数。这里得 说明一下,有个经常会出错的地方,IE下利用attachEvent注册的处理函数调用时this指向不再是先 前注册事件的元素,这时的this为window对象了
9. call apply bind
改变this的指向,
call函数的功能就是把当前的this指向作为函数来执行,并且该函数的this指向传入call的参数 call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向。 JavaScript 的一大特点是,函数存在「定义时上下文」和「运行时上下文」以及「上下文是可以改变的」这样的概念。 var Pet = { words : '...', speak : function (say) { console.log(say + ''+ this.words) } } Pet.speak('Speak'); // 结果:Speak... var Dog = { words:'Wang' } //将this的指向改变成了Dog Pet.speak.call(Dog, 'Speak'); //Pet.speak('Speak')结果: SpeakWang this 指向所属的对象 这里的this指向必须是引用类型。 如果this被强行改变为值类型,那么能够转为对应包装类型的都会转,不能转的 指向window 设置方法的调用对象(方法的this)时用; 需要注意的是两者传参方式不同: call():参数直接传入 apply():数组格式传入
sunshine15666