手把手教你实现三种绑定方式(call、apply、bind)
关于绑定首先要说下this的指向问题。
我们都知道:
函数调用时this指向window
对象调用函数时this指向对象本身
看下面得例子:
// 1
function test(){
const name = 'test1';
console.log(this.name)
}
constname = 'test2'
test() // test2
// 当前函数调用指向了window,所以打印的为test2 // 2
var obj = {
name:'test1',
get(){
console.log(this.name)
}
}
var name = 'test2';
obj.get() // test1
// 当前通过对象调用。this指向obj,打印test1 // 3
var obj = {
name:'test1',
get(){
console.log(this.name)
}
}
var name = 'test2';
var fn = obj.get;
fn() // test2
// 将obj.get作为值赋值给fn,执行fn,这时候相当于通过函数执行,this重新指向
那如何将this指向到我们指定的对象中呢?
js提供改变this指向的三种方法:call、apply、bind
其中call和apply执行改变this的同时会执行函数,bind是会返回一个函数。
而call与apply的区别在于参数,call可以传多个参数,而apply传一个数组作为参数。下面来看看实现:
模拟实现call
Function.prototype.myCall = function(thisArg, ...argumentArr){
if(typeof this !== 'function') {
throw new TypeError(`${this} is not function`)
};
if(thisArg === undefined || thisArg === null){
thisArg = window;
}
//生成一个对象
var obj = Object.create(thisArg)
obj['fn'] = this;
// 通过对象执行函数将this指向该对象
var result = obj['fn'](...argumentArr)
delete obj['fn'];
return result
} var obj = {
name:'test1',
get(data1, data2){
console.log(this.name, data1, data2)
}
}
obj.get.myCall({name: 'test2'}, 1, 2, 3) // test2,1,2 // 原理就是通过传入的新的对象来执行这个函数,就是通过对象调用函数的方式
模拟实现apply
Function.prototype.myApply = function(thisArg, argumentArr){
if(typeof this !== 'function') {
throw new TypeError(`${this} is not function`)
};
if(thisArg === undefined || thisArg === null){
thisArg = window;
}
if(argumentArr === undefined || argumentArr === null){
argumentArr = []
}
var obj = Object.create(thisArg)
obj['fn'] = this;
var result = obj['fn'](...argumentArr)
delete obj['fn'];
return result
} var obj = {
name:'test1',
get(data1, data2){
console.log(this.name, data1, data2)
}
}
obj.get.myApply({name: 'test2'}, [1, 2, 3]) // test2,1,2 // 我们发现与call唯一的不同就是入参,call使用rest 参数,将多余的参数整合成argument形式,而apply入参直接是数组
模拟实现bind
Function.prototype.myBind = function(thisArg, ...argumentArr){
if(typeof this !== 'function') {
throw new TypeError(`${this} is not function`)
};
if(thisArg === undefined || thisArg === null){
thisArg = window;
}
var self = this
var bindfn = function(){
return self.call(thisArg, ...argumentArr)
}
bindfn.prototype = self.prototype
return bindfn
} var obj = {
name:'test1',
get(data1, data2){
console.log(this.name, data1, data2)
}
}
const fn = obj.get.myBind({name: 'test2'}, 1, 2, 3)
fn() // test2,1,2 // 相比于前两个bind会有不一样,bind使用到了闭包,
// 我们之前知道函数执行this是指向window,但是这里我们执行却指向了我们的目标对象,实现这样的方式就是闭包的原因
如果我们没有赋值操作执行var self = this,而是直接使用this执行的话
this.call(thisArg, ...argumentArr)
这个时候this是指向window的,这个时候会报this.call is not a function。当我们进行赋值给self ,那么这个时候self 就形成了返回的函数fn的专属背包而不被销毁,每当我们执行fn的时候取到的this都是obj.get方法
手把手教你实现三种绑定方式(call、apply、bind)的更多相关文章
- v-bind绑定属性样式——class的三种绑定方式
1.布尔值的绑定方式 <div id="demo"> <span v-bind:class="{‘class-a‘:isA ,‘class-b‘:isB ...
- js this详解,事件的三种绑定方式
this,当前触发事件的标签 在绑定事件中的三种用法: a. 直接HTML中的标签里绑定 onclick="fun1()"; b. 先获取Dom对象,然后利用dom对象在js里绑定 ...
- Dom事件的三种绑定方式
1.事件 2. onclick, onblur, onfocus, 需求:请写出一个行为,样式,结构,相分离的页面. JS, CSS, HTML, 示例1,行为结构样式粘到一起的页面: & ...
- Binding 中 Elementname,Source,RelativeSource 三种绑定的方式
在WPF应用的开发过程中Binding是一个非常重要的部分. 在实际开发过程中Binding的不同种写法达到的效果相同但事实是存在很大区别的. 这里将实际中碰到过的问题做下汇总记录和理解. 1. so ...
- JavaScript三种绑定事件的方式
JavaScript三种绑定事件的方式: 1. <div id="btn" onclick="clickone()"></div> // ...
- AutoLayout的三种设置方式之——NSLayoutConstraint代码篇
AutoLayout是从IOS 6开始苹果引入来取代autoresizing的新的布局技术,该技术有三种设置方式,等下我来为大家一一叙述一下. 在说三种设置方式前,我们先简单的说一下autolayou ...
- JavaScript 三种绑定事件方式之间的区别
JavaScript三种绑定事件的方式: 1. <div id="btn" onclick="clickone()"></div> // ...
- Asp.Net中的三种分页方式
Asp.Net中的三种分页方式 通常分页有3种方法,分别是asp.net自带的数据显示空间如GridView等自带的分页,第三方分页控件如aspnetpager,存储过程分页等. 第一种:使用Grid ...
- Service组件 总结 + 绑定理Service三种实现方式 Messager + Binder + AIDL
在Android中进程按优先级可以分为五类,优先级从高到低排列: - 前台进程 该进程包含正在与用户进行交互的界面组件,比如一个Activity - 可视进程 该进程中的组件虽然没有和用户交互,但是仍 ...
随机推荐
- Libraries
Math.ceil() The Math.ceil() function returns the smallest integer greater than or equal to a given n ...
- 11- jmeter主要元件
元件分类 HTTP请求默认值(请求行,请求头,空行,消息体) HTTP信息头管理器: HTTPcookie管理器(1.更真实的模拟用户行为 ,多个请求的关联.第一个请求没有cookie第二个就带了co ...
- Android进程的so注入--Poison(稳定注入版)
本文博客地址:http://blog.csdn.net/qq1084283172/article/details/53869796 Android进程的so注入已经是老技术了,网上能用的Android ...
- POJ1548最小路径覆盖
题意: 给你一个DAG,然后问你最少多少条路径能覆盖所有需要覆盖的点. 思路: 最小路径覆盖,太明显了,每个点向它右下方的点连边,然后...没啥难的地方,不说了. #inclu ...
- UVA10870递推关系(矩阵乘法)
题意: 给以个递推f(n) = a1 f(n - 1) + a2 f(n - 2) + a3 f(n - 3) + ... + ad f(n - d), for n > d.,给你n ...
- hdu3706基础的单调队列
题意: 解释题意不如直接把这个题粘贴过来,因为题目很短题意很容易懂. Give you three integers n, A and B. Then we define Si = Ai mod B ...
- Windows核心编程 第七章 线程的调度、优先级和亲缘性(下)
7.6 运用结构环境 现在应该懂得环境结构在线程调度中所起的重要作用了.环境结构使得系统能够记住线程的状态,这样,当下次线程拥有可以运行的C P U时,它就能够找到它上次中断运行的地方. 知道这样低层 ...
- Sublime 快捷生成HTML 插件安装
更多精彩关注公众号 1 安装 Package Control1.1 ctrl + ` 呼出控制台1.2 复制(不要带最外层的双引号,该代码仅适用于sublime text 3)"import ...
- L SERVER 数据库被标记为“可疑”的解决办法
问题背景: 日常对Sql Server 2005关系数据库进行操作时,有时对数据库(如:Sharepoint网站配置数据库名Sharepoint_Config)进行些不正常操作如数据库在读写时而无故停 ...
- LeetCode 26. 删除有序数组中的重复项
双指针法 分析: 设置两个指针:p1,p2,初始p1指向数组的第一个元素,p2指向第二个元素 1)如果p1的值 == p2的值,就让p2后移一位 2)如果p1的值 != p2的值,修改p1的下一个元素 ...