apply,call和bind的使用及区别
1、用途
1)apply,call和bind都是 用来改变this的指向
2)apply和call会让当前函数立即执行,而bind会返回一个函数,后续需要的时候再调用执行
2、this指向问题
this的指向有以下四种情况:
1)如果函数中的this没有调用对象,则this指向window(严格模式下,this为undefined)
2)如果函数中this被不包含子对象的对象调用,则this指向调用它的对象
3)如果函数中this被包含多级对象的对象调用,则this指向调用它的上一级对象
4)如果我们调用了对象,并将其赋值给某个变量,然后在需要的时候再去调用执行它,则此时this也是指向的window对象,如:
var a = obj.myFunc;
a();
var name="zhang";
var age=18;
var obj={
name:"liu",
myAge:this.age,
myFun:function(){
console.log(this); // this指向obj
console.log(this.name+";"+this.age)
}
} obj.myAge // 18
obj.myFun()
上图是我们很常用的一个对象属性的获取和方法的调用,在我们获取obj.myAge属性时,这里的this实际是window对象,所以我们去找window.age,找到的是全局参数age=18
在调用myFun()方法时,本着谁调用this就指向谁的基本原则,此时this指向的是obj对象,所以我们输出的this.name为liu,this.age为undefined
上面的例子如果不太好理解的话,我们看下面这个更直观的例子:
var name="zhangsan";
function showName(){
console.log(this);
console.log(this.name);
}
showName();
我们在这里直接定义了一个方法,并且调用了它,上面说了,谁调用函数,函数里面的this就指向谁,但是我们这里直接调用了showName(),并没有明确说明是谁调用了它啊,其实这里我们可以理解为window.showName(),即this实际上是指向的window。
3、apply和call
1)先来看看call是如何实现的:
Function.prototype.call=function(context){
// 这里的this指向demo函数
console.log(this);
context=context?Object(context):window;
context.fn=this;
var args=[];
// 参数从1开始循环因为第一个参数是context
for(var i=1;i<arguments.length;i++){
args.push("arguments["+i+"]");
}
// 这里执行context.fn() 即上面的demo(),所以this指向了context,但是因为我们没有传递context,所以this指向了window
var r = eval("context.fn("+args+")")
delete context.fn;
return r;
}
var name="test"
function demo(){
console.log(this)
console.lot(this.name)
}
demo.call();
1) 当我们传递了context时,context为我们传递的对象;否则为window对象。
2) 谁调用,this指向谁,我们通过demo.call 调用了call方法,所以这里的this指向的时demo函数
3)将传递的参数放进args中
4)通过eval函数执行我们的context.fn,即上面的demo函数
5)demo函数中,this指向的时call方法中的context,这里时window对象
6)this.name即window.name
2)call其实是apply的一个语法糖,他们的作用都是用于改变上下文的指向,区别在于,call接受多个参数,而apply接受的是一个数组
var db={
name:"dema"
}
var obj={
name:"obj",
myFunc:function(from,to){
console.log(this);
console.log(this.name+"来自:"+from,+"去往:"+to);
}
}
obj.myFunc.call(null,'北京','上海') // this 指向window,this.name=undefined,from=北京,to=上海
obj.myFunc.call(db,'北京','上海'); // this指向db,this.name='dema',from=北京,to=上海
obj.myFunc.apply(db,['北京','上海']); // this指向db,this.name='dema',from=北京,to=上海
上面例子中,我们分别调用了call和apply,并传入了参数null,db和地名,从上面的call的实现中,可以看到,我们接受的第一个参数是上下文context,用于改变this的指向。
所以上面第一行,传入的context为null,则this指向window,第二行和第三行,都传人了context为db,所以this此时是指向db的,即this.name=db.name
4、bind
bind也是用于改变上下文的指向,它和call一样,接受多个参数。
bind和apply,call的区别在于,bind返回一个方法,用于后面调用,apply和call会直接执行
function print(a,b,c){
console.log(a,b,c)
}
var fn = print.bind(null,'D')
fn('A','B','C') // D,A,B
apply,call和bind的使用及区别的更多相关文章
- 让你弄懂 call、apply、bind的应用和区别
call.apply.bind使用和区别 // 有只猫叫小黑,小黑会吃鱼 const cat = { name: '小黑', eatFish(...args) { console.log('this指 ...
- 使用call、apply、bind继承及三者区别
js里的继承方法有很多,比如:使用原型链的组合继承.es6的Class.寄生继承以及使用call.apply.bind继承.再说继承之前,我们先简单了解下它们的区别. 一.区别: 同:三者都是改变函数 ...
- call,apply,bind的用法及区别
<script> function test(){ console.log(this) } // new test(); //函数调用call方法的时候,就会执行. //call的参数:第 ...
- bind,call,applay的区别
方法调用模式: 当一个函数被保存为对象的一个方法时,如果调用表达式包含一个提取属性的动作,那么它就是被当做一个方法来调用,此时的this被绑定到这个对象. var a = 1 var obj1 = { ...
- 动态作用域与this +apply和call +bind
词法作用域是一套关于引擎如何寻找变量以及会在何处找到变量的规则. (函数作用域和块作用域) JavaScript 中的作用域就是词法作用域,也就是静态作用域,由定义代码决定 动态作用域似乎暗示有很好的 ...
- js call apply caller callee bind
call apply bind作用类似.即调用一个对象的一个方法,以另一个对象替换当前对象. call 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) ...
- jQuery中的bind() live() delegate()之间区别分析
jQuery中的bind() live() delegate()之间区别分析 首先,你得要了解我们的事件冒泡(事件传播)的概念,我先看一张图 1.bind方式 $('a').bind('click', ...
- Jquery中bind和live的区别
Jquery中绑定事件有三种方法:以click事件为例 (1)target.click(function(){}); (2)target.bind("click",function ...
- Bind和Eval的区别详解
原文:Bind和Eval的区别详解 1.简单描述Eval和Bind的区别 绑定表达式 <%# Eval("字段名") %> <%# Bind("字段名& ...
- [jQuery]on和bind事件绑定的区别
on和bind事件绑定的区别 一个demo展示 <!DOCTYPE html> <html lang="zh"> <head> <titl ...
随机推荐
- SQLServer stuff函数
STUFF ( character_expression , start , length ,character_expression ) 参数 character_expression 一个字符数据 ...
- PHP如何防止注入及开发安全
1.PHP注入的基本原理 程序员的水平及经验也参差不齐,相当大一部分程序员在编写代码的时候,没有对 用户输入数据的合法性进行判断,使应用程序存在安全隐患.用户可以提交一段数据 库查询代码,根据程序返回 ...
- PHP 自动加载类
类的自动加载 (Autoloading Classes) 在编写面向对象(OOP) 程序时,很多开发者为每个类新建一个 PHP 文件. 这会带来一个烦恼:每个脚本的开头,都需要包含(include)一 ...
- C/C++代码静态分析工具调研
C/C++代码静态分析工具调研 摘自:https://www.jianshu.com/p/92886d979401 简述 静态分析(static analysis)是指在不执行代码的情况下对其进行分析 ...
- php cURL error 60: SSL certificate problem: unable to get local issuer certificate 解决办法
错误例子如下: php5.6以上的版本会出现这种问题 关于“SSL证书问题:无法获取本地颁发者证书”错误.很明显,这适用于发送CURL请求的系统(并且没有服务器接收请求) 1)从https://cur ...
- 使用Commons math做数值计算
使用Commons math做数值计算 觉得有用的话,欢迎一起讨论相互学习~Follow Me 最近使用jmetal做多目标的时候,想用一些简单的方法求最大值最小值方差和协方差矩阵,但是原生代码真的是 ...
- 获取Django model中字段名,字段的verbose_name,字段类型
如下app:ywreport下存在model:Game: class Game(models.Model): name = models.CharField(u'游戏名称',max_length=30 ...
- JS正则验证数字格式2
之前的博文:JS验证正数字,正则的一种正数规则1,中isNaN可以判断内容是否为数字,但是这种判断出来的数字,有的不是数字的标准格式.那篇博文中尝试了下用正则验证,但是忘了一种情况,小数点后无数字,小 ...
- CSS Position定位过多是否会影响浏览器渲染速度
一直有个传说就是页面里的Position多了会影响浏览器渲染速度,今天做个测试看看结果如何. 检验的方法: 动态创建一定数量的div > 开始计算时间 > 导入css文件渲染 > o ...
- SQL触发器中的inserted表和deleted表
开发也有年头了,但是触发器确实用的比较少,但是无容置疑触发器确实不错, 最近项目要求需要用到的触发器特别多.频繁,觉得很有必要记录和积累下. 在触发器语句中用两个特殊的表一个是deleted表和ins ...