cycold / cycold.github.io

Please dot not star...
4 stars 1 forks source link

event 继承 #149

Closed cycold closed 6 years ago

cycold commented 7 years ago
/**
 * Created by cycold on 17/02/2017.
 */

let EventEmitter = require("events")
let util = require("util")
let e = new EventEmitter()

console.log("this in global: %j", this)

e.on("a", function (arg) {
    // 事件中回调函数的this指向的就是挂载该事件的对象
    console.log(e === this)
    console.log('this in event callback: %j', this)
})
e.emit("a")

// 现在需要让Person类可以具有事件定义的功能
function Person(name = "eric") {
    // 注意这里调用EventEmitter方法,是为了将EventEmitter函数中不在EventEmitter.prototype中属性给挂载到当前的this中
    // 注意这里和原型util.inherits(Person, EventEmitter)继承不同, 原型继承只是仅仅继承了EventEmitter.prototype中的属性方法,
    // 但是EventEmitter这个函数也会直接定义一些属性,而这些属性是不在EventEmitter.prototype里面的,所以这里不直接调用一下是没有全部继承完的
    // 比如this.domain, this._events, ...这些属性是直接在EventEmitter函数里, 不在EventEmitter.prototype, 不这么调用一下,就会丢失这些属性了
    EventEmitter.call(this)

    this.name = name
}
// 只要让Person继承自EventEmitter即可
// Person.prototype = EventEmitter.prototype //修改了Person.prototype 会影响 EventEmitter.prototype
// Person.prototype.text = "text

// 使用inheris继承就不会出现修改了Person.prototype 会影响 EventEmitter.prototype
// util.inherits(Person, EventEmitter)
// util.inherits就等价于下面 因为里面调用的是 Object.setPrototypeOf(Person.prototype, EventEmitter.prototype)
// 而 Object.setPrototypeOf 实际上就是设置 对象的__proto__属性
// Person.prototype.__proto__ = EventEmitter.prototype
// Person.prototype.text = "text"

// 使用Object.create 这会创建一个新的对象 这个新的对象原型指向EventEmitter.prototype
// 这样Person.prototype 就和 EventEmitter.prototype分开了,他们就不相等了 这样Person.prototype已修改不会影响到EventEmitter.prototype
Person.prototype = Object.create(EventEmitter.prototype)
// 一般原型对象prototype都会一个constructor属性指向自己构造器的函数 Object.create返回的对象中的constructor还指向这EventEmitter 这个函数
// 所以这里要做一下更正 将其指向正确的构造函数
Person.prototype.constructor = Person

let p = new Person()
p.on("n", function () {
    // 这里的this指向就是p这个对象,因为回调函数是挂载在p这个对象上的
    console.log("\nafter 2s the name is : %s", this.name)
})

setTimeout(() => {
    p.emit("n")
}, 2000)
cycold commented 7 years ago
/**
 * Created by cycold on 17/02/2017.
 */

let EventEmitter = require("events")
// EventEmitter是一个函数
/**
 * 比如EventEmitter有如下的定义
 *
 * function EventEmitter() {
 *    this._events = []
 *    this._maxListeners = this._maxListeners || undefined;
 * }
 *
 * EventEmitter.prototype.on = function(){
 *    console.log(this._events)
 * }
 *
 * EventEmitter.prototype.emit = function(){
 *   console.log(this._events)
 * }
 */
// 定义一个构造函数(类), 需要继承EventEmitter类
function Person(name = "eric") {
    // 注意这里一定要这么调用一下, 是为了继承EventEmitter实例对象本身的属性, 这些属性不在EventEmitter.prototype对象中
    EventEmitter.call(this)   // call super constructor. 相当于别的语言的调用父类的构造函数一样
    this.name = name
}
// 肯定需要继承原型了
Person.prototype = Object.create(EventEmitter.prototype)
// 更新constructor 因为之前的constroctor还是EventEmitter,显然不正确
Person.prototype.constructor = Person

let p = new Person()
p.on('name', function () {
    console.log("\nname: %s", this.name) // 这里的this执行 p
})
setTimeout(() => { p.emit("name") }, 2000)