对象解析

javascript 本质没有 Class, 原型继承
javascript 对象:实例对象、函数对象、原型对象

实例对象

1
2
3
4
var people = new Student()

// people --> 实例对象
// Student -> 构造函数

构造函数在实例对象创建后进行调用,作用是对实例对象进行初始化操作

原型对象:实例对象和函数对象的父对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function people(name){
this.name=name;
console.log(this.name);
}

var student=new people("咸鱼");

// student --> 实例对象
// people --> 构造函数
// 实例对象和构造函数的关系
student.constructor==people;
// true
student instanceof people
// true 检查对象是否是构造函数的实例对象

proto

表示:实例对象通过 __proto__ 直接访问原型对象
除了 null undefined,javascript 中所有对象、原始类型都有 proto 属性

通过 __proto__ 属性修改对象的原型:非常慢且影响性能
ECMAScript 2015 规范中被准确的定义

获取、设置对象的原型

Object.getPrototypeOf、setPrototypeOf
Reflect.getPrototypeOf、setPrototypeOf

prototype

表示:构造函数通过 prototype 直接访问原型对象
构造函数都包含该属性(new 操作符生成的对象),指向原型对象

实例对象(__proto__) === 构造函数(prototype)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 因为Object是一个函数,函数的构造器都是Function
Object.__proto__ === Function.prototype // true

// 通过函数字面量定义的函数的__proto__属性都指向Function.prototype
(function(){}).__proto__ === Function.prototype // true

// 通过对象字面量定义的对象的__proto__属性都是指向Object.prototype
({}).__proto__ === Object.prototype // true

// Object函数的原型的__proto__属性指向null
Object.prototype.__proto__ === null // true

// 因为Function本身也是一个函数,所以Function函数的__proto__属性指向它自身的prototype
Function.__proto__ === Function.prototype // true

// 因为Function的prototype是一个对象,所以Function.prototype的__proto__属性指向Object.prototype
Function.prototype.__proto__ === Object.prototype // true

constructor

原型对象的属性,指向构造函数

关系图

原型链

实例对象.proto.proto.proto.null

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
function Person(name){
this.name = name
showInfo('基类构造函数...')
}

Person.prototype.SayHello = function() {
showInfo('基类构造函数的prototype方法...')
showInfo(`Hello,I'm ${this.name}`)
}

function Employee(name, salary){
showInfo('子类构造函数...')
Person.call(this, name)
this.salary = salary
}

Employee.prototype = new Person('employee.prototype')
Employee.prototype.ShowMetheMoney = function() {
showInfo(`${this.name} $ ${this.salary}`)
}

let a = new Person('Bill')
let b = new Employee('Steve', 1333)

a.SayHello()
b.SayHello()
console.log(a.SayHello == b.SayHello)

// a.ShowMetheMoney()
b.ShowMetheMoney()

showInfo(JSON.stringify(a))
showInfo(JSON.stringify(b))

New 原理

1
2
3
4
5
6
7
8
9
function New(Fn) {
// 创建一个空对象
let obj = new Object()
// 将新对象的原型指针指向构造函数的原型
obj.__proto__ = Fn.prototype
// 处理参数
let result = Fn.apply(obj, [].slice.call(arguments, 1))
return typeof result === "object" ? result || obj : obj
}
  1. 创建一个新对象
  2. 将构造函数的作用域赋给新对象(this 指向新对象)
  3. 执行构造函数中的代码(为新对象添加属性)
  4. 返回新对象

演示示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
var Person = {
Create: function(name, age){
this.name = name
this.age = age
},
SayHello: function(){
console.log(`hello, i'm ${this.name}`)
},
HowOld: function(){
console.log(`${this.name} is ${this.age} years old.`)
}
}

function anyfun(){ console.log('anyfun...')}
anyfun.prototype = Person
var BillGates = new anyfun()