摘要:引子独家解析原型继承已经比较全面的分析了自定义函数类型,内置基本类和内置对象类型的的以及的原型链。鉴于函数是的一等公民,另辟新篇介绍函数的原型及其应用。函数本身也是对象,它遵循独家解析原型继承所描述的自定义函数类型对象的原型法则。
引子
独家解析Javascript原型继承已经比较全面的分析了自定义函数类型,JS内置基本类(undefined, null, bool, number, string, symbol)和JS内置对象类型(Error, Date, Function)的design-time的prototype, 以及run-time的__proto__原型链。鉴于函数是JS的一等公民,另辟新篇介绍函数的原型及其应用。
JS函数类型的构造通常情况下定义一个函数:
function add1(a, b) { return a + b; } console.log(add1(1,2)) //3
通过new Function也能构造:
var add2 = new Function("a", "b", "return a + b"); console.log(add2(1,2)) //3
两种方式达到的目的是一致的。而add1和add2的run-time __proto__都是Function.prototype, 可以看作add1和add2都是透过new Function构造出来的,而function关键子就是调用new Function构造的便利途径。
add1.__proto__ = Function.prototype //true add2.__proto__ = Function.prototype //true
函数本身也是对象,它遵循独家解析Javascript原型继承所描述的自定义函数类型对象的原型法则。
//add1 创自于Function类型,是Function的实例 add1.__proto__ //[Function] add instanceof Function //true // add1 也继承了object类型的原型 add1.__proto__.__proto__ //{} add1 instanceof Object //true // 所以add1 run-time __proto__原型链的顶端同样是null add1.__proto__.__proto__.__proto__ // nullAOP编程实现
至此我们了解到,透过funtion关键字定义的函数,实质是Fuction类型的实例,和通过new Function方式构造本身是一样的。所以我们通过修改Function的design-time的prototype,来实现面向切面编程(AOP)
值得一提的是:我们(程序员)一般情况下只推荐修改design-time的prototype,而不去更改run-time的__proto__, 否则修改run-time的__proto__会造成程序难以维护和阅读,增加不确定的运行错误。Object.setPrototypeOf可以更改对象实例run-time的__proto__
面向切面编程(AOP,Aspect-Oritented Programming), 简而言之,可理解为函数调用时,在该函数执行前或/和执行后做一些通用的工作,比如做log,记录执行时间等。这需要一个代理函数,把原始函数打扮成具有做log等功能的新函数。实际中调用该代理函数
function foo() { console.log("foo runs"); } foo(); // foo runs
现在我们想在foo函数执行前后分别打印log,而不修改foo函数本身。
Function.prototype.before = function() { var _self = this; return function() { console.log("before foo calls"); return _self.apply(this, arguments); } } Function.prototype.after = function() { var _self = this; return function() { var ret = _self.apply(this, arguments); console.log("after foo calls"); return ret; } } //这里foo就具有了执行前后打印log的功能 foo = foo.before().after(); foo(); // before foo calls // foo runs // after foo calls
把打印log的功能提出来,做成更通用的逻辑。
Function.prototype.before = function(beforeFn) { var _self = this; return function() { beforeFn.apply(this, arguments); return _self.apply(this, arguments); } } Function.prototype.after = function(afterFn) { var _self = this; return function() { var ret = _self.apply(this, arguments); afterFn.apply(this, arguments); return ret; } } //包装成具有log功能的新的foo函数 foo = foo.before(function() { console.log("foo enters") }).after(function(){ console.log("foo exits") }); foo(); // foo enters // foo runs // foo exits
由此,可把函数调用和通用的log能功能挂接(hook)起来了。
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/84030.html
摘要:支持的类型的内置数据类型罗列如下自定义自定义这三种类型的赋值是同类似的。这根不同,这因为是没有包装类新增的基本类型,只支持函数式赋值,不支持字面量和函数构造。 JavaScript支持的类型 JS的内置数据类型罗列如下: undefined null bool number string function object Function Date ...
摘要:面向对象实现代码动物发声汪汪喵喵调用代码动物发声喵喵动物发声汪汪当要增加一种动物时,只需增加一个继承,不会影响其他已有的动物逻辑。所以的继承和的原型继承,可谓殊途同归。 传统面向对象的继承和多态 我们知道C++/Java/C#等面向对象语言,都原生地支持类的继承。继承的核心作用大抵是创建一个派生类,并使其复用基本类(即父类)的字段和/或方法。并且派生类可以重写基本类的方法。这样基本类和...
摘要:每一个由构造函数创建的对象都会默认的连接到该神秘对象上。在构造方法中也具有类似的功能,因此也称其为类实例与对象实例一般是指某一个构造函数创建出来的对象,我们称为构造函数的实例实例就是对象。表示该原型是与什么构造函数联系起来的。 本文您将看到以下内容: 传统构造函数的问题 一些相关概念 认识原型 构造、原型、实例三角结构图 对象的原型链 函数的构造函数Function 一句话说明什么...
摘要:设计模式是以面向对象编程为基础的,的面向对象编程和传统的的面向对象编程有些差别,这让我一开始接触的时候感到十分痛苦,但是这只能靠自己慢慢积累慢慢思考。想继续了解设计模式必须要先搞懂面向对象编程,否则只会让你自己更痛苦。 JavaScript 中的构造函数 学习总结。知识只有分享才有存在的意义。 是时候替换你的 for 循环大法了~ 《小分享》JavaScript中数组的那些迭代方法~ ...
摘要:使用新的易用的类定义,归根结底也是要创建构造函数和修改原型。首先,它把构造函数当成单独的函数且包含类属性集。该节点还储存了指向父类的指针引用,该父类也并储存了构造函数,属性集和及父类引用,依次类推。 原文请查阅这里,略有删减,本文采用知识共享署名 4.0 国际许可协议共享,BY Troland。 本系列持续更新中,Github 地址请查阅这里。 这是 JavaScript 工作原理的第...
阅读 2249·2021-09-27 13:35
阅读 520·2019-08-30 15:55
阅读 781·2019-08-30 15:53
阅读 525·2019-08-30 15:52
阅读 2111·2019-08-30 12:59
阅读 2202·2019-08-29 16:42
阅读 1329·2019-08-26 18:26
阅读 2440·2019-08-26 13:48