`

Javascript学习笔记 What is "this"

阅读更多
在JavaScript中,每当我们使用函数或者阅读已经写好的函数时,我们经常会看到里面用到this关键字的情况。

对于一个JS的初学者(尤其是对于有“主流”语言编程经验的人),会觉得this是让人凌乱的东西。

为了理解this,我们需要理解函数的调用方法。

在《Javascript Good Parts》一书中,将函数分为了四种调用方式:
方法调用;
函数式调用;
构造器调用;
apply(call)调用。
通读《Javascript Good Parts》的4.3节(2009年4月第一版)后,我对调用方式做了一个简短的总结。

当每个函数被调用的时候,他将会收到两个参数:this和arguments。为了方便起见,我们先写一个函数。

// 例1
var f = function(x, y) {
      var count = x + y + this.z;
      this.total = count;
      console.log(this.total);
};

当函数被调用的时候,就会得到this和arguments。

一、arguments是什么?
arguments是比较好理解的,它是一个传入实际参数的数组。这里之所以用“实际参数”,是为了和this相对应,在我们的例子中,arguments就是x和y。

由于有arguments的存在,所以js可以不必在函数定义的时候规定参数,比如上一个函数完全可以写成。

// 例2
var f = function() {
      var count = arguments[0] + arguments[1] + this.z;
      this.total = count;
      console.log(this.total);
};

虽然上面的函数可读性变差了,但是它和例1的功能是一样的。

基于以上原理,JS并不会支持如Java一样重载,如果有这样的代码:
// 例3
var o = {
    f: function(){ console.log(1); },
    f: function(){ console.log(2); },
};
//注意,这段代码没有错误的,JS真是自由的国度。
但是o只会承认第二的方法,即,后面的芳芳会覆盖前面的。

二、开始this吧

下面到了this,其实上面提到的四种调用方式的区别,从this的角度看,只是this所代表的地方不同。

2.1 方法式调用。
这要求函数必须在一个对象里面,比如:
// 例4
var o = {
    f: function() {
        console.log(this); //
    }
};
当我们使用o.f()的时候,打印出来的就是对象o。
可以看出,函数作为方法调用中,函数使用的this就是函数所在的对象。

2.2 函数式调用。
// 例5
var f = function() {
    console.log(this);
};
f()执行的时候,打印出来的是全局对象。如果你使用浏览器的开发者工具(比如打开Chrome,按F12后用Console界面)输入例子,你会得到Window对象。

2.3 构造器式调用。
// 例6
var Fun = function() {
    console.log(this);
};
Fun.prototype.x = function() {
    return 1;
};
Fun.prototype.y = 2;
对于例6中的函数,当我们执行var f = new Fun();的时候,this是什么呢?是Fun.prototype,即Fun的原型链。

2.4 apply/call式调用
我们先了解一下apply和call调用函数的方式:
Fun.apply(Obj, [x, y]);
Fun.call(Obj, x, y);
以上两个方式,都是以Obj为对象,以x和y为参数,调用方法Fun。所不同的是apply要求参数是数组,call要求参数挨个传入。
这样我们就可以方法式调用来理解apply式的调用。

我们大致可以了解this是什么了,this就是当前函数的执行环境。那么以下几个理解或许有助于我们记忆。
如例5中函数式调用,可以把f()看作是window.f();
例6中new的调用方式可以看成Fun.call(Fun.prototype, null),当然最后还有需要把生成结果返回给f;
再进一步,所有的前三种调用方式都可以用call来模拟。如例4中o.f()可以看做f.call(o, null),而例5中f()可以看做f.call(window, null);
而把this和arguments并列理解,也就可以解释为什么函数调用时,为什么要function.apply(object, arguments)了。

三、还有几个问题
以上的解释可以理解函数调用中大部分this的问题,但是我们要注意几个问题。
3.1 匿名函数的调用。
(function() { console.log(this); })();
JS很自由,它允许函数没有名字,这种情况下,this仍然指向全局对象(浏览器中为window)。

3.2 方法中函数式的调用。
这个说法很拗口,但是确有存在。
// 例7
var o = {
    f: function() {
        var innerF = function() {
            console.log(this);
        };
        innerF();
    }
};
当我们使用o.f();的时候,innerF也被顺便调用了,但是打印出来的结果仍然是全局对象。
这很让人头疼,如果说例5中f()打印出来的是全局对象是因为函数f就写在window下,这里innerF距离window隔了好几层。
但是现实如此,我们只能接受。具体原因估计要查ECMAScript最初开发者的交流邮件!

这里就引入了一个问题,如果innerF想调用对象o的代码怎么办?
好在可以“曲线救国”:
var o = {
    f: function() {
        var that = this;
        var innerF = function() {
            console.log(that);
        };
        innerF();
    }
};
当使用o.f();的时候,打印出来的就是对象o,而不是全局对象。

3.3 回调函数中的this。
// 例8
var f = function(cb) {
    cb();
};
var o = {
    callback: function() {
        console.log(this);
    }
};

f(o.callback);的结果仍然是window,可见函数的调用方式决定着this,把this和arguments作为参数理解,就更容易理解了。
当然回调函数被调用的方式是由原函数决定的。
对例8稍作修改,就可以得到不一样的结果。
// 例9
var f = function(callback) {
var innerO = {
x: 1,
cb: callback
};
innerO.cb();
};

var o = {
callback: function() {
console.log(this);
}
};

f(o.callback);
var f = function(callback) {
    var innerO = {
        x: 1,
        cb: callback
    };
    innerO.cb();
  
};
var o = {
    callback: function() {
        console.log(this);
    }
};
执行例9的f(o.callback);,打印结果是innerO对象。所以回调函数的使用就要看原函数的作者的意图了。

以上对于this的理解只是表象的总结,深入的了解需要查阅资料和了解浏览器的解析器

诚所谓,路漫漫其修远兮,吾将上下而求索。
var f = function(cb) {
cb();
};

var o = {
callback: function() {
console.log(this);
}
};

f(o.callback);
var f = function(cb) {
cb();
};

var o = {
callback: function() {
console.log(this);
}
};

f(o.callback);
var f = function(cb) {
cb();
};

var o = {
callback: function() {
console.log(this);
}
};

f(o.callback);
var f = function(cb) {
cb();
};

var o = {
callback: function() {
console.log(this);
}
};

f(o.callback);
分享到:
评论

相关推荐

    HTML+CSS+JavaScript教程学习笔记.zip

    HTML+CSS+JavaScript教程学习笔记HTML+CSS+JavaScript教程学习笔记 HTML+CSS+JavaScript教程学习笔记HTML+CSS+JavaScript教程学习笔记 HTML+CSS+JavaScript教程学习笔记HTML+CSS+JavaScript教程学习笔记 ...

    JavaScript学习笔记,javascript基础知识,基础语法整理.pdf

    JavaScript基础知识点总结 JavaScript是一种高级的、动态的、基于对象的客户端脚本语言。它是在网页上执行的脚本语言,能实现网页的交互功能。下面是该资源中的重要知识点总结: 一、 JavaScript 基本概念 * ...

    Javascript学习笔记PPT

    Javascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript学习笔记PPTJavascript...

    javascript学习笔记讲解版参考.pdf

    JavaScript学习笔记讲解版参考.pdf是一份详尽的教程,涵盖了从基础到进阶的JavaScript知识。这份笔记首先从CSS样式表开始,引导读者理解网页样式的设置与应用。 1. CSS(Cascading Style Sheets)样式表是用于控制...

    JavaScript学习笔记.pdf

    JavaScript学习笔记是一本关于JavaScript编程语言的教材,该教材通过丰富的实例,系统地介绍了JavaScript的基础知识和实际应用技巧,帮助读者一步步掌握客户端编程技术。本书共分为九章,每一章都有其特定的主题,...

    我的javascript学习笔记

    根据提供的文件信息,可以看出这份“我的javascript学习笔记”主要涵盖了JavaScript中的几个关键概念和技术要点,包括正则表达式、AJAX以及一些JavaScript的核心语言特性。接下来将这些知识点进行详细的整理和解释。...

    前端学习笔记网站(HTML5+CSS3+JavaScript前端网页web课程设计).rar

    前端学习笔记网站(HTML5+CSS3+JavaScript前端网页web课程设计).rar前端学习笔记网站(HTML5+CSS3+JavaScript前端网页web课程设计).rar前端学习笔记网站(HTML5+CSS3+JavaScript前端网页web课程设计).rar ...

    javascript笔记 javascript笔记

    <a href="javascript:prompt('What is your name?')">Click ``` - **解释:** 用户点击链接后会弹出一个输入对话框让用户输入名字。 ### JavaScript与DOM操作 JavaScript可以用来动态地修改文档对象模型(DOM),...

    Javascript学习笔记(传智播客视频学习笔记+代码)

    "Javascript学习笔记(传智播客视频学习笔记+代码)"是一份全面介绍JavaScript基础知识的学习资源,适用于初学者。这份笔记结合了传智播客的web前端培训视频内容,提供了丰富的理论讲解和实践代码,帮助读者从零开始...

    JavaScript 学习笔记集和代码库

    这个“JavaScript学习笔记集和代码库”涵盖了该语言的基础知识、进阶技巧以及实用示例,对于想要深入理解和掌握JavaScript的初学者或有经验的开发者来说,都是一个宝贵的资源。 首先,让我们来讨论JavaScript的基础...

    javascript学习笔记

    javascript学习笔记

    JavaScript学习笔记-适合初学者

    本学习笔记专为初学者设计,旨在帮助新接触JavaScript的人快速掌握这门语言的核心概念和实用技巧。 首先,"JavaScript特效.chm"可能是一份关于JavaScript实现的各种网页特效的教程。这些特效可能包括图片轮播、下拉...

    JavaScript 入门 新手学习笔记

    这篇"JavaScript入门新手学习笔记"提供了全面的学习资源,适合初学者系统性地掌握这一技术。 笔记可能包含了以下关键知识点: 1. **基础语法**:JS的基础包括变量(var、let、const)、数据类型(如字符串、数字、...

    Javascript学习笔记___自学实用

    JavaScript学习笔记——深入理解基础与函数 在JavaScript中,学习基础知识是至关重要的,因为它是所有进一步编程技巧的基础。首先,我们需要了解JavaScript中的数据类型。在JavaScript中,有五种简单的数据类型:...

    很有价值的javascript学习笔记

    ### JavaScript 学习笔记知识点详解 #### 一、JavaScript 基础概念 - **JavaScript 与 Java 的区别**:JavaScript 和 Java 是两种完全不同的编程语言。Java 是一种静态类型语言,而 JavaScript 是动态类型的解释性...

    JavaScript学习笔记,当时看黑马的视频记录的

    JavaScript学习笔记,当时看黑马的视频记录的

Global site tag (gtag.js) - Google Analytics