js基础和常考面试题(上)|小册免费学

266 阅读4分钟

原始类型

以前的原始类型有 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)

functiontypeof 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中只有三种转换的情况,转字符串、布尔和数字

image.png

如图,其中有一处错误,Boolean、函数、Symblo 转字符串都是 true, 只有boolean为true才是转成true

let a = funciton(){}
a.toString()//`funciton(){}`

boolean

在条件判断时,除了 undefined, null, false, NaN, '', 0, -0,其他所有值都转为 true,包括所有对象

对象转原始类型

www.cnblogs.com/f6056/p/108…

对象转换的时候会调用内置的[[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 决定.

  • 本文正在参与「掘金小册免费学啦!」活动, 点击查看活动详情