Javascript中的this,call,apply,bind函数-阿里云开发者社区

开发者社区> 鱼儿小猫> 正文

Javascript中的this,call,apply,bind函数

简介: 链接 this call与apply bind 一个有意思的示例 参考资料 1 链接 个人博客: alex-my.xyz CSDN: blog.csdn.net/alex_my 2 this 对于顶层对象的概念: 在浏览器中是window,但是node和Web Worker里面没有window。 浏览器和Web Worker中self也指向
+关注继续查看


1 链接

个人博客: alex-my.xyz

CSDN: blog.csdn.net/alex_my

2 this

  • 对于顶层对象的概念:
    • 在浏览器中是window,但是node和Web Worker里面没有window。
    • 浏览器和Web Worker中self也指向顶层对象,但node中没有。
    • 在node里面,顶层对象是global,但其它环境不支持。
  • 在严格模式下,未指定环境对象而调用函数,则 this 值不会转型为 window/global等。 除非明确把函数添加到某个对象或者调用call,apply,bind,否则 this 值将是 undefined
  • 这里使用的是node,支持ES6。运行测试用例node test.js
  • 三种调用模式来判断this的值。

    // 方法调用
    // 当一个函数被保存为对象的一个属性时,成为方法。调用时,this指向这个对象
    
    var handle = {
        name: 'Handle Name',
        init: function() {
            console.log(this.name, this);
        }
    }
    handle.init();  // 输出 Handle Name { name: 'Handle Name', init: [Function: init] }
    
    // 普通函数调用(非ES6的箭头函数)
    // 在严格模式下,thisundefined,输出 undefined false
    // 在非严格模式下,this指向全局,输出 global, true
    
    var normal = function () {
        console.log(this, this === global);
    }
    normal();
    
    // ES6箭头函数
    // this指向调用它的对象
    
    function Timer() {
        this.s1 = 0,
        this.s2 = 0,
    
        // 箭头函数,this指向调用其的Timer,这里会改变Timer.s1
        setInterval(() => { 
            this.s1++;
            console.log('箭头函数: ', this);    // this: Timer { s1: 11, s2: 0 }
        }, 1000);
        // 指向全局,这里并不会改变Timer.s2
        setInterval(function () { 
            this.s2++; 
            console.log('普通函数', this);      // this: global
        }, 1000);
    }
    
    var timer = new Timer();
    setTimeout(() => { console.log('s1: ', timer.s1) }, 3500)   // 输出 s1: 3
    setTimeout(() => { console.log('s2: ', timer.s2) }, 3500)   // 输出 s2: 0

3 call与apply

  • 二者作用差不多,会修改函数体内的this指向。

    function log() {
        console.log(this === global, this === undefined, this);
    }
    
    var foo = { 
        name: 'Foo'
    }
    
    log();
    log.call(foo);
    log.apply(foo);
    
    // 严格模式下输出
    // log():           false true undefined
    // log.call(foo):   false false { name: 'Foo' }
    // log.apply(foo):  false false { name: 'Foo' }
    
    // 非严格模式下输出
    // log():           true false global
    // log.call(foo):   false false { name: 'Foo' }
    // log.apply(foo):  false false { name: 'Foo' }
    • 以上表明经过call/apply处理后,this均指向了foo。
  • 二者传入参数的方式不同

    • 第一个参数做为当前对象,也就是this对象。
      • 不传或者传null, undefined, 会使得this指向global(非严格模式下)。
    • call: 参数要一个一个全部传入,不许使用arguments对象。
    • apply: 参数通过组成数组传入,或使用arguments对象。
    function log(x, y) {
        console.log(this, x, y);
    }
    
    var a = function(x, y) {
        log.call(a, x, y);          // 输出 1 2
        log.call(a, arguments);     // 输出 { '0': 1, '1': 2 } undefined,不能正确获取参数
    
        log.apply(a, x, y);         // 报错,需要组成数组
        log.apply(a, arguments);    // 输出 1 2
        log.apply(a, [x, y]);       // 输出 1 2, 通过数组
    }
    a(1, 2);

4 bind

  • 对于给定的函数,会创建一个绑定函数,这个绑定函数的this会指向传入的对象
function log(x, y) {
    console.log(this === global, this.name, x, y);
}

var people = {
    name: 'People'
}
// 输出 true undefined, log函数在全局上下文中调用, this指向global
log(1, 2);   

// 输出 false 'People'
// log中的this被绑定为people
var foo = log.bind(people);
foo(1, 2);

// 也可以这样
var foo2 = log.bind(people, 1, 2);
foo2();

5 一个有意思的示例

  • 来源: Alex MacCaw 如何面试前端工程师:GitHub 很重要
  • 关于apply

    function log() {
        var args = Array.prototype.slice.call(arguments);
        args.unshift(new Date().toLocaleString());
        console.log.apply(console, args);
    }
    
    log('hello', 'world');          // 输出 2017-8-12 18:11:26 hello world
    log('hello');                   // 输出 2017-8-12 18:11:26 hello
  • 关于bind

    var User = {
        count: 1,
    
        getCount: function () {
            return this.count;
        }
    };
    
    // 函数在User的上下文中执行,this指向User
    console.log(User.getCount()); // 输出 1
    
    // func在全局上下文中执行,this指向global(非严格模式下)
    var func = User.getCount;
    console.log(func()); // 输出 undefined
    
    // 绑定了User,this指向User
    var func2 = User.getCount.bind(User);
    console.log(func2()); // 输出 1

6 参考资料

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
[实变函数]5.6 Lebesgue 积分的几何意义 $\bullet$ Fubini 定理
1 本节推广数学分析中的 Fubini 定理. 为此, 先引入 (1)(从低到高) 对 $A\subset \bbR^p, B\subset\bbR^q$, $$\bex A\times B=\sed{(x,y);x\in A, y\in B} \eex$$ 称为 $A$ 与 $B$ 的直积 (direct product).
1037 0
thinkphp对数据库操作有哪些内置函数
原文:thinkphp对数据库操作有哪些内置函数 getModelName() 获取当前Model的名称 getTableName() 获取当前Model的数据表名称 switchModel(type,vars=array()) 动态切换模型 table() 设置当前操作的数据表 field...
926 0
【JavaScript框架封装】在实现一个自己定义类似于JQuery的append()函数的时候遇到的问题及解决方案
版权声明:本文为博主原创文章,未经博主允许不得转载。更多学习资料请访问我爱科技论坛:www.52tech.tech https://blog.csdn.net/m0_37981569/article/details/81087543 主要问题: 在刚开始创建了这个函数之后,使用的时候,总是会出现一个问题,就是按照正常步骤给一个ID选择器添加子节点的时候正常,但是到了给一个class选择器的元素添加的时候始终只能添加一个。
831 0
VB编程:利用CallByName函数对对象进行操作
VB编程:利用CallByName函数对对象进行操作
4 0
HDOJ 1004题 Let the Balloon Rise strcmp()函数
Problem Description Contest time again! How excited it is to see balloons floating around. But to tell you a secret, the judges' favorite time is guessing the most popular problem.
966 0
find_if 仿函数错误:cannot convert 'this' pointer from 'const CActTaskData' to 'CActTaskData &'
今天编写find_if的仿函数时编译报错,cannot convert 'this' pointer from 'const CActTaskData' to 'CActTaskData &'。        struct act_task_finder { public: act_task_finder(const OBJID objId) : m_ObjId
776 0
PHPpraffa也有了,一个PHP版本的阿里云函数计算与API网关的开发框架
发布了Python版本的函数计算与API网关的开发框架后,一直觉得对不起PHP,因为公司一直是用PHP的,我这弄了个Python,实在不该,对了,(Python版本说明点这里。 PHPpraffa是什么? PHPpraffa 是praffa的PHP版本。
1141 0
详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数
详解C++ 编写String 的构造函数、拷贝构造函数、析构函数和赋值函数
11 0
MFC全局函数开局——AfxGetApp解剖
MFC中有不少的全局函数,方便在不同对象中获取不同的内容或创建不同的对象。主要全局函数有: AfxWinInit() AfxBeginThread() AfxEndThread() AfxFormatString1() AfxFormatString2() AfxMessageBox()   AfxOutPutDebugString()   AfxGetApp() AfxGetMainWnd() AfxGetInstance() AfxRegisterClass() 这些函数从名称上可见豹斑(功能)。
891 0
+关注
鱼儿小猫
无证开发程序员。
111
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
文娱运维技术
立即下载
《SaaS模式云原生数据仓库应用场景实践》
立即下载
《看见新力量:二》电子书
立即下载