zoukankan      html  css  js  c++  java
  • JavaScript中七种函数调用方式及对应 this 的含义

    this 在 JavaScript 开发中占有相当重要的地位,不过很多人对this这个东西都感觉到琢磨不透。要真正理解JavaScript的函数机制,就非常有必要搞清楚this到底是怎么回事。

    函数调用方式不同,this 含义也跟着不同。JavaScript语言中有七种调用函数方式:
     
    第一种:调用方法
    var obj = {
        method: function() { alert(this === obj); }
    }
    obj.method();
    上面这行obj.method()显然method是作为方法被调用,这种情况下,函数体中的this绑定的就是method的宿主对象,也就是obj。
    从这种调用方式我们得出第一定律:
    第一定律:以方法方式调用函数,this则绑定宿主对象。

    第二种:调用全局函数
    var method = function(){alert(this === window);}
    method();
    上面这个函数是个全局函数。我们知道,全局变量或函数都相当于window对象的属性。也就是说,上面这句实际上等同于下面这句:
    window.method = function(){alert(this === window);}
    window.method();
    既然这样,那么这里 this 绑定到 window 对象就显而易见,很容易理解了。相当于方法调用模式的一个特例,并不违背第一定律。

    第三种:全局函数内调用内部函数

    var m_ext = function() {
        alert(this === window);
        var m_inner = function() {
            alert(this === window);
        }
        m_inner();
    }
    m_ext();
    执行上面这段代码,你会惊讶的发现,两个布尔表达式的值都是真。也就是说子函数孙函数,只要是以函数的方式调用,this 就铁了心绑定 window 对象了。从这种调用方式我们得出第二定律:
    第二定律:不论子函数孙函数,只要是以函数的方式调用,this 就铁了心绑定 window 对象。

    第四种:方法内调用内部函数

    var obj = {};
    obj.method = function() {
        alert(this === obj);
        var m_inner = function() {
            alert(this === window);
        }
        m_inner();
    }
    obj.method();
    执行上面这段代码,第一个this绑定到obj你不奇怪,第二个this绑定到window其实也不奇怪。它仍然遵守第二定律,也就是不论子函数孙函数,只要是以函数的方式调用,this 就铁了心绑定 window 对象。

    第五种:作为构造函数调用

    function Person(name, age){
        this.name = name;
        this.age = age;
    }
    var john = new Person('John', 38);
    alert(JSON.stringify(john));
    你会说,哇,这很眼熟。生成某个类的新对象啊。Javascript就是这么另类,函数确实可以这么调。
    这次弹出的是这样一个字符串:{"name":"John","age":38}。哇,这次我明明没在函数定义里写return 语句,它却主动返回了一个对象给我。没错,即便你在函数定义里return某个东西,它也不会理你。(注意:如果你return一个function就会有惊喜,不信你试试看)。从这种调用方式我们得出第三定律:
    第三定律:如果在一个函数本身没有返回值,在其前面加上 new 调用,就会创建一个连接到该函数 prototype 属性的新对象,再把 this 绑定到该对象,然后执行该函数,最后返回该对象。如果该函数有返回值,且返回值为字符串/数字/布尔值等简单对象的话,该返回值会被丢弃。但如果该函数的返回值为对象,函数或者数组等复杂对象的话,该函数则会返回该返回值,抛弃this绑定的对象。据我测试,如果返回值是一个函数时,该函数会返回undefined。我暂时还不知道为什么会这样。

    第六种:用函数对象的apply方法调用

    var my_concat = function(stra, strb){
        alert(this);
        return stra + '' + strb;
    }
    var param = ['hello', ' world']
    alert(my_concat.apply('bullshit', param));

    你一定注意了,在这里 this 绑定的是apply方法的第一个参数 'bullshit'。从这里我们得出第四定律:
    第四定律:用方法的apply/call方法调用方法时,this 则被绑定到apply/call方法的第一个参数。
    想谁就是谁,嗯,吴妈也行。JavaScript的程序员们好幸福哦。

    第七种:用函数对象的call方法调用
    var my_concat = function(stra, strb){
        alert(this);
        return stra + '' + strb;
    }
    alert(my_concat.call('bullshit', 'hello',' world'));

    对啦,你或许会多问一句,apply 的第二个参数有什么规定?call方法和apply又有什么不同?嗯 ,真是勤学好问,我就再啰嗦一下说说apply和call:

    apply 和 call 的区别:

    apply要求第二个参数必须是数组。否则就会报
    TypeError: second argument to Function.prototype.apply must be an array. 而call则没这么严格啦,第二个参数要什么类型?随意啦,还可以有第三个第四个第五个第六个....啦。

    我想我说的够清楚了。感谢《JavaScript The Good Parts》和《JavaScript Definitive Guide》,要不然我也弄不明白呢!

  • 相关阅读:
    java数据库编程之DAO模式
    java数据库编程之JDBC
    java数据库编程之初始Mysql
    java数据库编程之常用的操作用户和赋权限
    java数据库编程之事务、视图、索引、备份、恢复
    java数据库编程之嵌套子查询及exists的使用
    .net窗体程序的基础知识及详细笔记
    sql sever 基础知识及详细笔记
    java基础知识及详细笔记
    计算机基础知识及笔记
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/3656401.html
Copyright © 2011-2022 走看看