构造函数

em....,这章主要讲关于 面向对象、原型、原型链、继承。

面向对象

面向对象基本特征:封装继承多态,在es6之前没有 class(类),js是通过构造函数模拟的面向对象。

原型

原型(prototype)是一个简单的对象,主要用于实现对象的属性继承。 每个js对象都包含一个__proto__属性指向该对象原型。

原型链

原型链是由原型对象组成,每个对象都有__proto__属性,指向了创建该对象的构造函数的原型, __proto__将对象连接起来组成了原型链。是一个用来实现继承和共享属性的有限的对象链。

  • 属性查找机制:当查找对象的属性时,如果实例对象自身不存在该属性,则沿着原型链往上一级查找,找到时则输出,不存在时,则继续沿着原型链往上一级查找,直至最顶级的原型对象Object.prototype,如还是没找到,则输出 undefined
  • 属性修改机制:只会修改实例对象本身的属性,如果不存在,则进行添加该属性,如果需要修改原型的属性时,则可以用: b.prototype.x = 2;但是这样会造成所有继承于该对象的实例的属性发生改变。

构造函数

可以通过new 运算符新建一个对象的函数。

JavaScript 构造函数命名规范 驼峰式命名

实例

通过构造函数和 new 创建出来的对象,便是实例。

实例通过 __proto__ 指向原型,通过 constructor 指向构造函数

构造函数 - 原型 - 实例示例图

示例图

new运算符

  • 新生成一个对象
  • 链接到构造函数的原型: obj.__proto__ = Con.prototype
  • 执行构造函数,并绑定this到新建对象上
  • 返回新建对象(如果构造函数自己有return,且返回值类型为Function|Object时,则返回该值)

原理:

function myNew(Con, ...args) {
  if (typeof Con !== 'object' && typeof Con !== 'function' || !('constructor' in Con)) {
    throw new TypeError(`${Con} is not a constructor`)
  }
  const obj = Object.create(Con.prototype)

  const result = Con.call(obj, ...args)

  if (typeof result === 'object' && result !== null || typeof result === 'function') {
    return result
  }
  return obj
}
1
2
3
4
5
6
7
8
9
10
11
12
13

继承

es5构造函数继承

function Person(name) {
  this.name = name
}
Person.prototype.play = function() {
  console.log(this.name, 'play')
}

// 继承
function Student(name, age) {
  Person.call(this, name)
  this.age = age
}

Student.prototype = Object.create(Person.prototype)
Student.prototype.constructor = Student

Student.prototype.say = function() {
  console.log(this.name, this.age, 'say')
}














 
 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

es6 class 语法糖

class Person(name) {
  constructor(name) {
    this.name = name
  }

  play() {
    console.log(this.name, 'play')
  }
}

class Student extends Person {
  constructor(name, age) {
    super(name)
    this.age = age
  }
  say() {
    console.log(this.name, this.age, 'say')
  }
}











 

 





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

静态方法

/**
 * 静态方法|属性 不需要实例化 直接调用
 * Person.play()  Person.name 
 */

// es6
class Person {
  static name = 'person'
  static play() {
    console.log(Person.name)
  }
}

// es5
function Person() {}
Person.name = 'person'
Person.play = function() {
  console.log(Person.name)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
上次更新: 2021/10/20 下午4:40:42
贡献者: 陈书进