我们都学过 javascript 的面向对象, 在我学习的过程中, 一度有个问题困扰着我, 那就是在构造函数中, 如果使用了 this, 那么这个 this 指向的是谁? 如果在定义的原型方法中使用了 this, 那么这个 this 又指向谁了? 是构造函数, 原型, 还是实例? 到底是谁在决定?
- function Person(name, age) {
- this.name = name;
- this.age = age;
- }
- Person.prototype.getName = function() {
- return this.name;
- }
- var p1 = new Person('pan', 18);
- p1.getName();
构造函数其实就是普通的函数, 而 this 是在函数运行时才确定的. 那么是什么导致构造函数变得如此特别了?
与 new 关键字有关
如果我们自定义一个 New 方法, 来模拟关键字 new 的能力, 那么会有如下实现 (在此之前请先回忆一下 new 一个函数 会发生什么., 如果您没有想起来, 那就记住 new 一个函数, 生成一个实例对象).
- // 将构造函数以参数形式传入
- function New(func) {
- // 声明一个中间对象, 该对象为最终返回的实例
- var res = {};
- if(func.prototype !== null) {
- // 将实例的原型指向构造函数的原型
- res.__proto__ = func.prototype;
- }
- //ret 为构造函数执行的结果, 这里通过 apply,
- // 将构造函数内部的 this 指向修改为指向 res, 即为实例对象
- var ret = func.apply(res, Array.prototype.slice.call(arguments,1))
- // 当在构造函数中明确指定了返回对象时, 那么 new 的执行结果就是该返回对象
- if((typeof ret === 'object' || typeof ret === 'function') && ret !== null) {
- return ret;
- }
- // 如果没有明确指定返回对象, 则默认返回 res, 这个 res 就是实例对象
- return res;
- }
为了方便大家理解, 例子中做了一些注解. 通过 New 方法的实现可以看出, 执行时, 利用 apply 设定了传入的构造函数的 this 指向, 因此当使用 New 方法创建实例时, 构造函数中的 this 就指向了被创建的实例.
如果把当前函数看成基础函数, 那么高阶函数, 就是让当前函数获得额外能力的函数. 如果把构造函数看成基础函数, 那么 New 方法, 就是构造函数的高阶函数. 构造函数本就和普通函数一样, 没有什么区别. 但是因为 New 的存在, 它获得了额外的能力. New 方法每次执行都会创建一个新的中间对象, 并将中间对象的原型指向构造函数的原型, 将构造函数的 this 指向该中间对象. 这样统一逻辑的封装, 就是高阶函数的运用.
当然, 如果简单粗暴一点来理解, 则凡是接收一个函数作为参数的函数, 就是高阶函数. 但是如果这样理解, 那么我们还是用不好高阶函数. 因为正如阳波大神所说, 高阶函数其实是一个高度封装的过程, 理解它需要点想象力. 那么在接下来的系列中, 就借助几个例子, 来理解高阶函数的封装.
来源: https://juejin.im/post/5b23ac5af265da598d17d7df