手写call、apply、bind函数
栏目: JavaScript · 发布时间: 5年前
-
特点:
- 1)可以改变我们当前函数的this指向
- 2)还会让当前函数执行
Function.prototype.call = function (context) { if (typeof this !== 'function') { throw new TypeError(`${this} is not a function`) } context = Object(context) || window; context.fn = this; let args = []; for (let i = 1; i < arguments.length; i++) { args.push('arguments['+i+']'); } let r = eval('context.fn('+args+')'); delete context.fn; return r; } 复制代码
题目自测
function fn1() { console.log(this,arguments); console.log(1); } function fn2() { console.log(this,arguments); console.log(2); } fn1.call(fn2,1,2); // fn2 [1,2] 1 fn1.call.call.call.call.call(fn2,1,2); // {number:1} [2] 2 复制代码
-
思路解析
-
fn1.call(fn2,1,2)
-
1)
call
执行传入fn2
,1
,2
三个参数 -
2)
call
函数内部context = Object(fn2) = fn2
-
3)
fn2.fn = fn1
-
4)
args=['arguments[1]','arguments[2]']=[1,2]
-
5)
eval('context.fn('+args+')') = fn2.fn(1,2) = fn2.fn1(1,2)
-
1)
-
fn1.call.call.call.call.call(fn2,1,2)
-
1)
call
执行传入fn2
,1
,2
三个参数 -
2)
call
函数内部context = Object(fn2) = fn2
-
3)
fn2.fn = call
-
4)
args=['arguments[1]',arguments[2]]=[1,2]
-
5)
eval('context.fn('+args+')') = fn2.fn(1,2) = fn2.call(1,2)
-
6)
call
执行传入1
,2
两个参数 -
7)
call
函数内部context = Object(1) = Number{1}
-
8)
Number{1}.fn = fn2
-
9)
args=['arguments[1]']=[1]
-
10)
eval('context.fn('+args+')') = Number{1}.fn(2) = Number{1}.fn2(2)
-
注:多次调用
call
的时候其实是call
执行的时候内部又调用了一次call
,总共调用两次
-
1)
-
apply
函数
-
特点:
- 1)可以改变我们当前函数的this指向
- 2)还会让当前函数执行
Function.prototype.apply = function (context,args) { if (typeof this !== 'function') { throw new TypeError(`${this} is not a function`) } context = Object(context) || window; context.fn = this; if(!args){ return context.fn(); } let r = eval('context.fn('+args+')'); delete context.fn; return r; } 复制代码
new
操作符
-
特点
this
/* *基本使用 */ function Animal(type) { this.type = type ; } Animal.prototype.say = function () { console.log('say'); } let tiger = new Animal('tiger'); console.log(tiger); -------------------------------------------------------- /* *方法实现 */ function mockNew(){ let Constructor = [].shift.call(arguments); let obj = {}; // 新生成了对象 obj.__proto__ = Constructor.prototype; // 链接到原型 let r = Constructor.apply(obj,arguments) // 绑定`this` return r instance Object ? r : obj; //返回一个对象 } let tiger = mockNew(Animal,'tiger'); console.log(tiger); 复制代码
bind
函数
-
特点
-
绑定
this
指向 - 返回一个绑定后的函数(高阶函数原理)
-
如果绑定的函数被
new
执行 ,当前函数的this
就是当前的实例 -
new
出来的结果可以找到原有类的原型
-
绑定
Function.prototype.bind = function (context) { if (typeof this !== 'function') { throw new TypeError(`${this} is not a function`) } let that = this; let bindArgs = Array.prototype.slice.call(arguments, 1); function Fn() { }; function bindFn() { let args = Array.prototype.slice.call(arguments); /* * 绑定`this`指向 * 如果绑定的函数被`new`执行 ,当前函数的`this`就是当前的实例 */ that.apply(this instanceof bindFn ? this : context, bindArgs.concat(args)); } /*`new`出来的结果可以找到原有类的原型*/ Fn.prototype = that.prototype; bindFn.prototype = new Fn(); /*返回一个绑定后的函数*/ return bindFn; } 复制代码
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Modern PHP(中文版)
Josh Lockhart / 安道 / 中国电力出版社 / 2015-9 / 39
PHP正在重生,不过所有PHP在线教程都过时了,很难体现这一点。通过这本实用的指南,你会发现,借助面向对象、命名空间和不断增多的可重用的组件库,PHP已经成为一门功能完善的成熟语言。 本书作者Josh Lockhart是“PHP之道”的发起人,这是个受欢迎的新方案,鼓励开发者使用PHP最佳实践。Josh通过实践揭示了PHP语言的这些新特性。你会学到关于应用架构、规划、数据库、安全、测试、调试......一起来看看 《Modern PHP(中文版)》 这本书的介绍吧!