Skip to content

JavaScript

数据类型

基本类型

numberstringbooleanBigIntSymbolnullundefined

引用类型

objectArrayFunction...

Symbol

每个从 Symbol() 返回的 symbol 值都是唯一的,Symbol() !== Symbol() 永远返回 true
基本类型,不能用 new
入参都会 toString

判断类型

typeof

只输出 number,boolean,string,function,object,undefined
NaN 也输出 number
引用类型(数组、正则)只输出 object

instanceof

用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上

js
new Promise(() => {}) instanceof Promise // true

call

js
Object.prototype.toString.call()
console.log(toString.call(123)) // [object Number]
console.log(toString.call("123")) // [object String]
console.log(toString.call(undefined)) // [object Undefined]
console.log(toString.call(true)) // [object Boolean]
console.log(toString.call({})) // [object Object]
console.log(toString.call([])) // [object Array]
console.log(toString.call(function () {})) // [object Function]
console.log(toString.call(new Promise(() => {}))) // [object Promise]

遍历

  • for in 主要用于遍历对象的可枚举属性,包括自有属性、继承自原型的属性
  • Object.keys 返回一个数组,元素均为对象自有的可枚举属性
  • Object.getOwnPropertyNames 用于返回对象的自有属性,包括可枚举和不可枚举的

可枚举属性

Object.defineProperty 添加的方法默认不可枚举
基本包装类型的原型属性是不可枚举的,如 Object, Array, Number 等

原型链

原型链

  • Object 是所有对象的爸爸,所有对象都可以通过 proto 找到它
  • Function 是所有函数的爸爸,所有函数都可以通过 proto 找到它
  • 对象的 proto 属性指向原型, proto 将对象和原型连接起来组成了原型链
  • js 分为函数对象和普通对象,每个对象都有 proto 属性,但是只有函数对象才有 prototype 属性
  • 函数的 prototype 是一个对象
  • 函数的 prototype 指向了一个对象,而这个对象正是调用构造函数时创建的实例的原型

原型链

继承

prototype 的继承就是 js 的糟粕,能用 class 就用 class

class 继承

js
class Parent {
  constructor(name) {
    this.name = name
    this.className = "parent"
  }

  toString() {
    return "my name is " + this.name
  }
}

class Child extends Parent {
  constructor(name) {
    // 必须调用super
    super(name)
    this.className = "child"
  }
}

构造函数继承

调用 Parent 当作构造函数
proto 没有指向 Parent

js
function Child(name) {
  Parent.apply(this, arguments)
}

原型链继承

无法向父类传递参数
构造函数会被重写

js
function Parent(name) {
  this.name = name
  this.className = "parent"
  this.toString = function () {
    return "I have no name"
  }
}

function Child(name) {}

Child.prototype = new Parent()
Child.prototype.constructor = Child

组合继承

会调用两遍父类构造函数

js
function Parent(name) {
  this.name = name
  this.className = "parent"
  this.toString = function () {
    return "my name is " + this.name
  }
}

function Child(name) {
  // 调用第一遍
  Parent.apply(this, arguments)
  this.className = "child"
}

// 调用第二遍
Child.prototype = new Parent()
Child.prototype.constructor = Child

寄生继承

js
function extend(obj) {
  let clone = Object.create(obj)
  clone.toString = function () {
    return "I am child"
  }
  return clone
}

const child = extend(parent)

组合+寄生继承

js
function Child(name) {
  Parent.apply(this, arguments)
}

Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child

new 对象的过程

  • 创建一个空对象
  • 让空对象的 proto 指向构造函数的 prototype
  • 执行构造函数中的代码(为这个新对象添加属性)
  • 返回新对象

暂时性死区

js
console.log(num)
var num = 1

等价于

var num
console.log(num)
num = 1

let 和 const 能生成暂时性死区,提前使用会抛出错误

性能指标

来来来,前端性能监控,带你拿到正确的性能指标