`

你不知道的 JavaScript - “this”

阅读更多

JavaScript 里的 this 到底指得是什么?很多人都会告诉你 this 指的是当前对象。这样理解对么?在大多数情况下确实没错。比如我们经常会在网页上写这样的 JavaScript:

 

<input type="submit" value="提交" onclick="this.value='正在提交数据'" />

 

这里的this显然指的是当前对象,即这个提交按钮。通常,我们使用this的情况都与此类似。但是有什么情况不是这样的呢?

大家看看这个例子:

 

var foo = function() {
    console.log(
this);
}

foo();
new foo();

 

比较一下 foo() 和 new foo() 的运行结果,你会发现,前者 this 指向的并非 foo 本身,而是当前页面的window对象,而后者才真正的指向foo。这是为什么呢?

其实这牵涉到JavaScript的一条重要特性,就是所谓的“闭包”。闭包这个概念说复杂也不复杂,但也不是简单到能用一两句话说清。偶会在以后的文章中深入探讨这个Javascript 最重要的特性。现在,我要告诉大家的是,因为闭包的存在,JavaScript中的作用域变得相当重要。

所谓的作用域,简单的说,就是创建一个函数时在什么环境下创建的。而this变量的值,如果没有指定的话,就是函数当前的作用域。

 

在前面的例子里,foo() 函数是在全局作用域(这里就是window对象),所以this的值是当前的window对象。而通过 new foo() 这样的形式,其实是创建了一个foo()的副本,并在这个副本上进行的操作,所以这里的this就是foo()的这个副本。

 

这样讲可能有点抽象,大家来看个实际的例子:

 

<input type="button" id="aButton" value="demo" onclick="" />
<script type="text/javascript">
function demo() {
    
this.value = Math.random();
}

</script>

 

如果直接调用demo() 函数,程序就会报错,因为demo函数是在window对象中定义的,所以demo的拥有者(作用域)是window,demo的this也是window。而window是没有value属性的,所以就报错了。

图解

如果我们通过创建副本的方式,将这个函数的副本添加到一个HTML元素,那么他的所有者就成了这个元素,this也指代了这个元素:

 

document.getElementById("aButton").onclick = demo;

 

这样就将aButton的onlick属性设置为demo()的一个副本,this也指向了aButton。

图解

你甚至可以为多个不同的HTML元素创建不同的函数副本。每个副本的拥有者都是相对应的HTML元素,各自的this也都指向他们的拥有者,不会造成混乱。

图解

 

但是,如果你这样定义某个元素的onlick事件:

 

<input type="button" id="aButton" value="demo" onclick="demo()" />

 

点击这个button之后,你会发现,程序又会报错了——this又指向了window!

其实,这种方法并没有为程序创建一个函数,而只是引用了这个函数。

具体看一下区别吧。

 

使用创建函数副本的方法:

 

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><input type="button" id="aButton" value="demo" />
<script type="text/javascript">
var button = document.getElementById("aButton");
function demo() {
    
this.value = Math.random();
}

button.onclick
= demo;
alert(button.onclick);
</script>

 

得到的输出是:

 

function demo() {
    
this.value = Math.random();
}

 

使用函数引用的方法:

 

<input type="button" id="aButton" value="demo" onclick="demo()" />
<script type="text/javascript">
var button = document.getElementById("aButton");
function demo() {
    
this.value = Math.random();
}

alert(button.onclick);
</script>

 

得到的输出是:

 

function onclick() {
    demo();
}

 

这样就能看出区别了吧。函数引用的方式中,onclick事件只是直接调用demo()函数,而demo()函数的作用域仍旧是window对象,所以this仍然指向window。

图解

 

这样就又引出了一个问题:既然函数副本这么好用,为什么还需要函数引用的方法呢?答案是性能。每新建一个函数的副本,程序就会为这个函数副本分配一定的内存。而实际应用中,大多数函数并不一定会被调用,于是这部分内存就被白白浪费了。而使用函数引用的方式,程序就只会给函数的本体分配内存,而引用只分配指针,这样效率就高很多。程序员么,节约为主,恩

所以我们来看一个更好的解决方案:

 

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> --><script type="text/javascript">
function demo(obj) {
    obj.value 
= Math.random();
}

</script>
<input type="button" value="demo" onclick="demo(this)" />
<input type="button" value="demo" onclick="demo(this)" />
<input type="button" value="demo" onclick="demo(this)" />

 

这样,效率和需求就都能兼顾了。

 

最后再多讲一句:在前面的文章里,我特别强调了“如果没有指定this的话”。其实this是可以指定的。Function对象有两个方法:call()和apply()。这两个方法都支持指定一个函数中的this。有兴趣的话您可以去查一下Javascript的手册,看看这两个函数都是干什么用的。而我们经常用的 new foo() 可以用以下这段伪代码来描述:

 

<!--<br /> <br /> Code highlighting produced by Actipro CodeHighlighter (freeware)<br /> http://www.CodeHighlighter.com/<br /> <br /> -->function new (somefunction) {
    
var args = [].slice.call(arguments, 1);
    somefunction.prototype.constructor 
= somefunction;
    somefunction.apply(somefunction.prototype, args);
    
return somefunction.prototype;
}

 

现在明白了,在本文开头的第一个例子里,new foo() 的 this 为什么是 foo 了吧

分享到:
评论

相关推荐

    JavaScript高级-this绑定规则+箭头函数

    JavaScript中的`this`绑定规则是理解JavaScript面向对象编程的关键概念之一。`this`关键字在不同情况下会有不同的指向,主要取决于函数的调用方式。这里我们将深入探讨四种主要的`this`绑定规则:默认绑定、隐式绑定...

    Presentations-JavaScriptThis-源码.rar

    为了更深入地理解这些知识点,你可以通过解压`Presentations-JavaScriptThis-源码.zip`文件,查看其中的代码示例和讲解,进行实践操作。这将有助于你巩固理论知识,并提升解决实际问题的能力。同时,你也可以结合...

    ans-javascript-sdk:Analysys JavaScript SDK

    This is the official JavaScript SDK for Analysys. JavaScript SDK目录说明: demo——API调用演示 SDK——SDK文件 src——SDK源码 vue-demo——VUE框架API调用演示 安装 npm install ans-javascript-sdk --save ...

    angluo-javascript-239617.pdf

    这是因为在HTML中,`selectName`会被解析为`selectname`,与我们在JavaScript中定义的`selectName`不匹配,从而导致子组件无法正确接收。 解决这个问题的方法是将HTML中的prop属性名修改为`select-name`,与...

    李炎恢JavaScript-PDF

    在处理大型PDF时,优化和压缩是必不可少的。JavaScript可以用于减少文件大小,例如通过删除未使用的对象或压缩图像。`doc.optimize()` 和 `doc.saveAs()` 方法可以帮助完成这个任务。 10. **跨平台兼容性** 虽然...

    javascript中onclick(this)用法介绍

    本文将详细介绍JavaScript中一种常见的事件处理用法——onclick(this)。 首先,我们需要理解什么是onclick事件处理器。在HTML中,onclick是一个事件属性,用于指定当元素被点击时将调用的JavaScript代码。这个属性...

    javascript中this的指向问题总结

    JavaScript中this的指向还没搞明白?来这看看 你就懂啦~

    JavaScript程序设计-javascript中this的指向问题.pdf

    在JavaScript编程中,`this`关键字是一个至关重要的概念,它表示当前上下文中的对象引用。在不同的场景下,`this`的指向会有所不同,这往往让开发者感到困惑。以下是关于`this`指向问题的详细解释: 一、普通函数...

    JavaScript程序设计-javascript中的this.pdf

    JavaScript中的`this`关键字是一个非常重要的概念,它在不同上下文中具有不同的指向,这使得`this`成为JavaScript灵活但有时也复杂的一部分。`this`的动态绑定特性在编写JavaScript代码时需要特别注意,因为它会影响...

    JavaScript手册-中文文档

    JavaScript是Web开发中不可或缺的一部分,它是一种轻量级的、解释型的编程语言,主要用于增强网页的交互性。这份“JavaScript手册—中文文档”提供了一个全面的JavaScript学习资源,涵盖了从基础语法到高级特性的...

    计算机后端-Java-PHP视频教程javascript03-215 this是谁.wmv

    计算机后端-Java-PHP视频教程javascript03-215 this是谁.wmv

    JavaScript-使用javascript开发的搜索算法-searching.zip

    在JavaScript编程领域,搜索算法是实现数据查找功能的关键技术。搜索算法主要用于在数据结构(如数组、链表、树等)中寻找特定元素。这里我们将深入探讨几种常见的JavaScript搜索算法,包括线性搜索、二分搜索、哈希...

    11-this:从JavaScript执行上下文的视角讲清楚this_For_vip_user_0011

    在JavaScript中,`this`是一个特殊的关键词,它用于在函数或方法中引用当前上下文的对象。`this`的值取决于函数被调用的方式,而不是函数声明的位置,这与作用域链(由词法作用域决定)是两个独立的概念。在不同类型...

    Javascript的this详解

    - **箭头函数**:箭头函数不创建自己的`this`上下文,它继承自外层(父)作用域的`this`值。 - **事件处理程序**:在DOM事件处理程序中,`this`通常绑定到触发事件的元素。 - **异步回调**:在回调函数或Promise链中...

    Modern-JavaScript-starter-files.zip

    Modern JavaScript Video Project.This is the Modern JavaScript Repository. Suitable for learning how to use JavaScript.

    JavaScript程序设计javascript中this

    JavaScript中的`this`关键字是程序设计中的一个核心概念,它在不同上下文环境中有着不同的指向,这使得理解和掌握`this`的用法至关重要。在JavaScript中,`this`的值取决于函数调用的方式,而不是定义的方式,这为...

    Javascript中神奇的this

    1. `this`并不总是指向函数自身 许多人可能认为在函数内部,`this`应该指向函数本身,但在JavaScript中,情况并非如此。以下示例展示了`this`的误导性理解: ```javascript function fn(num) { this.count++; } fn...

    mastering-javascripts-this

    作者Derick Bailey通过一个持续多天的学习旅程,带领读者全面了解并掌握JavaScript中“this”的使用规则和机制,旨在解决读者在实际编程中对于“this”指向不定性的困惑。 在本书中,作者提出了一系列关于“this”...

    lab-javascript-advanced-algorithms.zip

    An exercise to practice JavaScript and use testing to create a solution. In this exercise, you will be able to: use data structures to organize your application information, learn how to model real...

Global site tag (gtag.js) - Google Analytics