方法调用模式:

当一个函数被保存为对象的一个方法时,如果调用表达式包含一个提取属性的动作,那么它就是被当做一个方法来调用,此时的this被绑定到这个对象。

  var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
obj1.fn()
//2 此时的this是指obj1这个对象,obj1.fn()实际上是obj1.fn.call(obj1),事实上谁调用这个函数,this就是谁。补充一下,DOM对象绑定事件也属于方法调用模式,因此它绑定的this就是事件源DOM对象。如:
document.addEventListener('click', function(e){ console.log(this); setTimeout(function(){ console.log(this); }, 200); }, false);
点击页面,依次输出:document和window对象
解析:点击页面监听click事件属于方法调用,this指向事件源DOM对象,即obj.fn.apply(obj),setTimeout内的函数属于回调函数,可以这么理解,f1.call(null,f2),所以this指向window。
 

把函数赋值之后再调用

var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
var fn1 = obj1.fn
fn1()//1
obj1.fn是一个函数function(){console.log(this.a)},此时fn1就是不带任何修饰的函数调用,function(){console.log(this.a)}.call(undefined),按理说打印出来的 this 应该就是 undefined 了吧,但是浏览器里有一条规则:

如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)

因此上面的this绑定的就是window,它也被称为隐性绑定。
如果你希望打印出2,可以修改fn1()fn1.call(obj1),显示地绑定this为obj1

回调函数

var a = 1
function f1(fn){
fn()
console.log(a)//1
}
f1(f2) function f2(){
var a = 2
}
改写代码如下:
var a = 1
function f1(){
(function (){var a = 2})()
console.log(a)//1
}
f1()
仍旧是最普通的函数调用,f1.call(undefined),this指向window,打印出的是全局的a。
借此,我们终于可以解释为什么setTimeout总是丢失this了,因为它也就是一个回调函数而已。
setTimeout(function() {
console.log(this)//window
function fn(){
console.log(this)//window
}
fn()
}, 0);

call

call 方法第一个参数是要绑定给this的值,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,默认指向window。

var arr = [1, 2, 3, 89, 46]
var max = Math.max.call(null, arr[0], arr[1], arr[2], arr[3], arr[4])//89

可以这么理解:

obj1.fn()
obj1.fn.call(obj1); fn1()
fn1.call(null) f1(f2)
f1.call(null,f2)

应用场景

求数组中的最大和最小值

var arr = [1,2,3,89,46]
var max = Math.max.apply(null,arr)//89
var min = Math.min.apply(null,arr)//1

将类数组转化为数组

var trueArr = Array.prototype.slice.call(arrayLike)
call、apply和bind函数存在的区别:

bind返回对应函数, 便于稍后调用; apply, call则是立即调用。

 
 
 
 
 
 
 
 

最新文章

  1. iOS常用库之Masonry
  2. android 使用LinearGradient进行字体渐变的效果
  3. 要做linux运维工程师的朋友,必须要掌握以下几个工具才行 ...
  4. 十天冲刺---Day4
  5. 转:理解Cookie和Session机制
  6. WinForm多线程学习文档
  7. poj1182(食物链)
  8. iOS开发——实战OC篇&环境搭建之Xib(玩转UINavigationController与UITabBarController)
  9. Ruby on Rails Tutorial 第二章 之 微博资源
  10. linux云计算集群架构学习笔记:用户管理和root用户密码重置
  11. Web Service相关工具的配置
  12. css3动画与js动画的一些理解
  13. 创建透明CEdit控件
  14. OSX MacVim + vim-lldb配置和使用心得
  15. 基于Spring Boot,使用JPA操作Sql Server数据库完成CRUD
  16. java中Collections.sort()方法实现集合排序
  17. bind、call和apply对比和使用
  18. Kubernetes & Docker
  19. luogu P1659 [国家集训队]拉拉队排练
  20. Cassandra 数据模型

热门文章

  1. @ResponseBody返回中文乱码
  2. 点击复制内容到剪切板(clipboard)
  3. Win/Lin 双系统时间错误的调整 (转)
  4. Oracle 命令
  5. UINavigationController 返回到各级目录
  6. 数电——全减器分析(用74HC138设计提示)
  7. 前后台交互实现点击超链接通过指定的 url 去网络或者文件服务器下载文件
  8. 机器学习进阶-图像基本操作-边界补全操作 1.cv2.copyMakeBoder(img, top_size, bottom_size, left_size, right_size, cv2.BORDER_REPLICATE) 进行边界的补零操作 2.cv2.BORDER_REPLICATE(边界补零复制操作)...
  9. ThreadLoacl 小记
  10. 保存对象报错with two open Sessions