从底层理解this是什么( 三 )
4.通过构造函数中设置咱们现在再来看一下通过new调用构造函数到底做了什么:
function polyNew(source, ...arg) {// 创建一个空的简单JavaScript对象(即{})let newObj = {};// 链接该对象(即设置该对象的构造函数)到另一个对象Object.setPrototypeOf(newObj, source.prototype);// 将步骤1新创建的对象作为this的上下文 ;const resp = source.apply(newObj, arg);// 判断该函数返回值是否是对象if (Object.prototype.toString.call(resp) === "[object Object]") {// 如果该函数没有返回对象 , 则返回this 。return resp} else {// 如果该函数返回对象 , 那用返回的这个对象作为返回值 。return newObj}}
显然我们看到 source.apply(newObj, arg), 所以构造函数其实也改变了this指向 , 将this指向从原函数换到了新构造出来的函数 。
解疑填坑
- this存放在哪里?this存放在每个执行上下文中
- this是如何出现 , 又是如何消失的?this随着执行上下文出现 , 当执行上下文被回收后 , 也随之消失
- this有什么作用?全局执行上下文中:this指向了 window 对象 , 方便我们来调用全局 window 对象 。 函数执行上下文中:this指向了调用该函数的对象 , 减少的参数的传递 , 原来如果需要在函数内部操作被调用对象 , 当然还需要将对象作为参数传递进去 , 而有了 this, 就不需要了 , 直接拿 this 就能操作被调用对象的属性 。
MDN:call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数 。
举个例子:
let bar = {myName : "dellyoung",}function foo(){console.log(this.myName)}foo.call(bar) // 打印出 dellyoung
也就是说:调用foo函数的时候 , 通过使用call() , 并且传入bar , 使得foo函数内部的this指向了bar实现call咱们就根据这个结论来实现一下call:
Function.prototype.dellCall = function (context = window,...param) {// 判断是函数才能调用call方法if (typeof this !== 'function') {return new TypeError("类型错误");}// 将this也就是被调用的函数 , 通过赋值给传入的对象 , 来达到将被调用的函数添加到传入的对象上的目的context.fun = this;// 用传入的对象来调用需要被调用的函数 , 并保留返回结果const resp = context.fun(...param);// 删除传入对象上被添加的函数 , 防止内存泄漏Reflect.deleteProperty(context, 'fun');// 返回结果return resp;};
其实核心很简单 , 咱们分析一下:- 将被调用的函数作为一个属性添加到传入的对象上
- 从而可以实现在传入的对象上 , 调用需要被调用的函数
- 咱们分析完发现核心原理还是:谁调用函数 , 函数的this指向谁
实现applyapply其实和call差不多 , 只不过传递参数的方式不同:
foo.call(obj,[param1,param2,...,paramN]) // 参数是数组 , 传入一个数组作为参数foo.apply(obj,param1,param2,...,paramN) // 参数非数组 , 可以传一串参数
咱们对上面的call稍微改一下就是apply了:Function.prototype.dellApply = function (context = window, param = []) {// 判断是函数才能调用call方法if (typeof this !== 'function') {return new TypeError("类型错误");}// 将被调用的函数作为一个属性添加到传入的对象上context.fun = this;// 在传入的对象上 , 调用需要被调用的函数const resp = context.fun(...param);// 删除传入对象上被添加的函数 , 防止内存泄漏Reflect.deleteProperty(context, 'fun');// 返回结果return resp;}
推荐阅读
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- 资本的价值观:996是福报?底层人物就是用命换钱?
- 数据|新基建时代,高大全的数据管理解决方案是怎样“炼”成的?
- 魅族 17 系列即将升级 Android 11 系统底层
- 官方爆料:魅族Flyme的Android 11底层安排上了?
- 菜鸟学编程,不懂C++ this指针?还不赶快来学一学
- 田间地头万亿级争锋:互联网巨头与垂直玩家共舞 供应链能力考验底层逻辑
- 深入理解Netty编解码、粘包拆包、心跳机制
- 魅族17升级Android 11系统底层倒计时 12·23内测招募
- 社区团购巨头纷纷入场,底层商贩、老百姓或将成为“鱼肉”
- HFL Redis_10_set类型底层存储数据结构