proto-hook

126 阅读1分钟

关于js 的钩子的说明

功能

  1. 对指定类的 的属性进行打钩子,注意 不同类的实例都会触发钩子 proto-hook
var ph = require("proto-hook")
var fs = require("fs")
var { readFileSync: _readFileSync, existsSync: _existsSync, readFile: _readFile, exists: _exists } = fs

ph.watchProto(fs, "readFileSync", {
	get() {
		return function (dir) {
			console.log("readFileSync", dir)
			return _readFileSync.call(fs, ...arguments)
		}
	}
})

ph.watchProto(fs, "readFile", {
	get() {
		return function (dir) {
			console.log("readFile", dir)
			return _readFile.call(fs, ...arguments)
		}
	}
})

ph.watchProto(fs, "existsSync", {
	get() {
		return function (dir) {
			console.log("existsSync", dir)
			return _existsSync.call(fs, ...arguments)
		}
	}
})

//其他: /proto.test.js

var {watchProto} = require("./proto")
var debug = require("debug")("test")
debug.enabled = true
class Parent {
  set pval(val) {
    debug("%cparent.pval set", "red")
    this.$$value = val
  }
  set size(val) {
    // return Math.random() * 10 + 10
    debug("%cparent.size set", "red")
    this.$size = val
  }
  get size() {
    debug("%cparent.size #get", "red")
    return this.$size
  }
}

class Base extends Parent {//
  constructor() {
    super()
    console.log("Base init")
    // console.log('\x1B[33m%s\x1b[0m:', "Base init");  //yellow
  }
  say() {

  }
  get name() {
    console.log("Base get#name")
    console.log(this)
    return 30
  }
  set name(val) {
    console.log("Base set.name")
    console.log(this)
    this.value = 33
  }
  set attr($var) {
    this.$var = $var
  }
}
var base = new Base()

watchProto(Base.prototype, "name")
watchProto(Base.prototype, "size")//__proto__
base.size = "base"
var base1 = new Base()
base1.size = "base1"// 钩子被触发
console.log("父属性:%s,%s", base.size, base1.size)
console.log("父属性:%s,%s", base.size, base1.size)
base.pval = "base.pval unhook"

// watchProto(Parent, "pval")
base.pval = "base.pval hook"
console.log(base.pval)

base.name = (Math.random() * 0xffffffffffffff).toString(36)
base1.name = (Math.random() * 0xffffffffffffff).toString(36)

console.log(`子属性:${base.name},${base1.name}`)

base.val = 55
console.log(base.name)
// console.log(Object.getOwnPropertyDescriptor(base.__proto__, "name"))
// console.log(Object.getOwnPropertyDescriptor(Base.prototype, "name"))


// let hasOwnProperty = Object.prototype.hasOwnProperty.call.bind(Object.prototype.hasOwnProperty)
/* require("util").inherits(Base, {
  prototype: {
    say1: () => {
      console.log("say")
    }
  }
}) */
console.clear()
var base0 = {}
Object.defineProperty(base0, "name", {value: "base0"})
watchProto(base0, "attr", {get(val) {console.log(val); return 20} })
watchProto(base0, "attr1", {get(val) {console.log(val); return val} })
base0.attr = 30
console.log(Object.getOwnPropertyDescriptor(base0, "attr"))
console.log("base0.attr:%s", base0.attr)
base0.attr1 = "attr1"
console.log(base0.attr1)
console.log("base0.attr:%s", base0.attr)
console.log(base0.attr1)
console.log(base0)

watchProto(Date.prototype, "getTime", {get(val) {console.log("Date#getTime"); return Date.prototype.getDay} })
console.log(new Date().getTime()) 

用proxy实现的钩子 见文件 ‘/protoByProxy.test.js’

var { proxyClass, proxyObject } = require("./protoByProxy")
var Array0 = proxyClass(Array)
console.log(new Array0().forEach(v => {
	console.log(v)
}))
class M {
	constructor() {
		this.w = 30
	}
	get x() {
		return this.w
	}
	set x(val) {
		this.w = val
	}
}
var obj = {
	a: 20
}

var objb = {
	set a(val) {
		this.val = 30
		console.log()
	},
	val: 50,
	get a() {
		return this.val
	}
}

var hookInstance = {
	watchObj(prop, val, that) {
		console.log("get", prop, val)
	},
	beforeObjChang(prop, val) {
		console.log("beforeObjChang", prop, val)
	},
	afterObjChang(prop, val) {
		console.log("afterObjChang", prop, val)
	}
}
var obj = proxyObject(obj, hookInstance)
console.log(obj.a)
obj.a = 30
var Mp = proxyClass(M, { instanceHook: hookInstance,hookBefore(args){ 
	console.log("构造前",args)
},hookAfter(args,res){
		console.log("构造后", args, res)
}})
var mp = new Mp()
console.log(mp.x)
mp.x = 50