原始类型
以前的原始类型有 boolean null undefined number string symbol
现在多了个BigInt,参考MDN:developer.mozilla.org/zh-CN/docs/…
我觉得可以这样记 2snb u 2个b开头的,n开头的,s开头的,一个u开头的
而死牛逼 u
注意点
原始类型只存值,不能调用方法,'2'.toString()可以调用是因为'2'被转成对象String
number类型是浮点型,0.1+0.2!=0.3
string类型的值不可变,无论调用什么方法
使用 typeof 运算符检查,只能检测出6种,null被认为是object,属于一个bug
对象类型
在计算机科学中, 对象是指内存中的可以被 标识符引用的一块区域.在js中,除了原始类型那么其他的都是对象类型了,我更倾向于说是引用类型。
其中typeof instance === "object"的有:任何 constructed 对象实例的特殊非数据结构类型,也用做数据结构:new Object,new Array,new Map,new Set,new WeakMap,new WeakSet,new Date,和几乎所有通过 new keyword 创建的东西。(null)
而function是typeof instance === "function",非数据结构,尽管也是object派生,也属于引用(不对请指正哈)
注意点
对象和原始类型的区别在于一个存值一个存地址
函数参数是对象时,函数执行时拿到传入对象的地址,如果对象的属性在函数里被改变,会影响外面的对象的~
typeof vs instanceof
MDN:记住 typeof 操作符的唯一目的就是检查数据类型,如果我们希望检查任何从 Object 派生出来的结构类型,使用 typeof 是不起作用的,因为总是会得到 "object"。检查 Object 种类的合适方式是使用 instanceof 关键字。但即使这样也存在误差。
- typeof可以用来判断除了null的原始类型,判断对象时都是
object,函数是function - instanceof可以用来判断一个对象的正确类型,内部机制是原型链
function f(a,b){
return a.__proto__ == b.prototype
}
- instanceof 的判断行为可以利用
Symbol.hasInstance编辑
class PrimitiveString {
static [Symbol.hasInstance](x) {
return typeof x === 'string'
}
}
console.log('hello world' instanceof PrimitiveString) // true
类型转换
js中只有三种转换的情况,转字符串、布尔和数字
如图,其中有一处错误,Boolean、函数、Symblo 转字符串都是 true,
只有boolean为true才是转成true
let a = funciton(){}
a.toString()//`funciton(){}`
boolean
在条件判断时,除了 undefined, null, false, NaN, '', 0, -0,其他所有值都转为 true,包括所有对象
对象转原始类型
对象转换的时候会调用内置的[[ToPrimitive]] 函数 逻辑如下:
如果对象具有toString()方法,则调用这个方法。如果它返回一个原始值,JavaScript将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。需要注意,原始值到字符串的转换。
如果对象没有toString()方法,或者这个方法并不返回一个原始值,那么JavaScript会调用valueOf()方法。如果存在这个方法,则JavaScript调用它。如果返回值是原始值,JavaScript将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。
否则,JavaScript无法从toString()或valueOf()获得一个原始值,因此这时它将抛出一个类型错误异常。
在对象到数字的转换过程中,JavaScript做了同样的事情,只是它会首先尝试使用valueOf()方法
当然也可以重写内部转换方法
let a = {
valueOf() {
return 0
},
toString() {
return '1'
},
[Symbol.toPrimitive]() {
return 2
}
}
1 + a // => 3
四则运算符
加法
- 运算中其中一方为字符串,那么就会把另一方也转换为字符串
- 如果一方不是字符串或者数字,那么会将它转换为数字或者字符串
1 + '1' // '11' 特征1
true + true // 2 特征2 都转成1
4 + [1,2,3] // "41,2,3" 特征2 都转成字符串
4 +2+ [1,2,3] //61,2,3" 特征2 但是正常的还是能正常算的
4 +2+111+'6'+ [1,2,3]//"11761,2,3"
'a' + + 'b' // -> "aNaN"//因为+b是NaN
//+'1'可以快速获得number类型 这我没懂
其他运算
只要其中一方是数字,那么另一方就会被转为数字
4 * '3' // 12
4 * [] // 0
4 * [1, 2] // NaN
比较运算符
- 如果是对象,就通过 toPrimitive 转换对象
- 如果是字符串,就通过 unicode 字符索引来比较
let a = {
valueOf() {
return 0
},
toString() {
return '1'
}
}
a > -1 // true
在以上代码中,因为 a 是对象,所以会通过 valueOf 转换为原始类型再比较值。
this
1.直接调用,指向window
2.被谁调用,指向谁
3.构造函数时,指向构造实例
4.call,apply,bind的第一个参数改变this指向
5.箭头函数没有自己的this,指向最近的外部普通函数的this,箭头函数对bind等无用
优先级:new>bind,箭头函数和bind互斥
bind的指向
let a = {}
let fn = function () { console.log(this) }
fn.bind().bind(a)() // => ?
// fn.bind().bind(a) 等于
let fn2 = function fn1() {
return function() {
return fn.apply()
}.apply(a)
}
fn2()
let a = { name: 'yck' }
function foo() {
console.log(this.name)
}
foo.bind(a)() // => 'yck'
不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定.
- 本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情