JavaScript中this用法学习笔记

JavaScript这门语言中,最令人迷惑的地方有三个,闭包、this、原型。针对大多数人,可以利用词法作用域等避开this的坑,但是我们不能一直生活在舒适区,要敢于打破砂锅问到底,对我们来说也是一种提升。

一、一般对this关键字的误解:

1、this指向函数自身

2、this指向函数词法作用域

我们可以看以下一段代码:

function test() {
test.a = 1;
this.a = 2;
console.log(test.a);
console.log(this.a);
console.log(test.a === this.a);
}

test();
console.dir(test);

在上面这段代码中,我们在全局声明一个方法test,给test中的a属性赋值1,当前方法中的this中的a属性赋值2,加入this指向函数自身,那么test.a === this,a并且都等于2.

下面我们来看下这段代码的运行结果:

从上可以看出,scopes为全局作用域window,this也指向这里,虽然函数本身也是一个对象,但是this并不指向这里。

有一点我们一定要记住,this是在运行时进行绑定的,并不是在编写时绑定的,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

既然this是在运行时绑定的,那我们有没有办法改变当前this的绑定,使其不指向window,而指向方法test呢?答案是肯定的,我们可以借助一些强制绑定方法,如call、apply、bind来改变this的指向,我们可以将代码改成下面这种方式:

function test() {
 test.a = 1;
 this.a = 2;
 console.log(test.a);
 console.log(this.a);
 console.log(test.a === this.a);
 }

 test.call(test);
console.dir(test);

运行结果如下:

接下来我们看下this是否指向函数的词法作用域,以下有段比较有意思的代码:

function parent() {
 var a = 2;

 function child() {
 console.log(this.a)
 }
 child();

 }
parent();

假如this指向函数的词法作用域,那么child方法中的this.a应该是存在,实际上的执行结果如下:

实际上,在JavaScript内部,作用域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过JavaScript代码访问,它存在JavaScript引擎内部。所以每当你想要把this和词法作用域的查找混合使用时,一定要提醒自己,这是无法实现的。

二、this的绑定规则

this的绑定规则大致分为以下几类:

2.1 默认绑定

2.2 隐式绑定

2.3 显式绑定

2.4 new绑定

2.1 默认绑定

上述示例中this的指向是指向window的,他们都有一个共同的特征,不带任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则

2.2 隐式绑定

隐式绑定首先需要考虑的规则就是调用位置是否有上下文对象,或者说是否被某个对象拥有或包含,例如:

这里的this就是指向对象obj。还有类似一些DOM事件的绑定,document.getElementById('xxx').addEventListener('click', function(){xxx});回调方法中的this是指向选择器选中的元素的。这种情况下可以简单的理解为this指向调用方法.前面的那个对象。

2.3 显式绑定

显示绑定在开发过程中运用的比较多,借助于这些显式绑定方法,可以直接改变当前方法的this指向,使得js语言非常的灵活。主要有call、apply和bind三种,基本使用如下:

 function sum() {
 console.log(this.a + this.b);
 }
 var obj1 = {
 a: 1,
 b: 2
 };
 var test = sum.bind(obj1);
 sum.call(obj1); //3
sum.apply(obj1); //3
test(); //3

注意事项:

call && apply第一个参数接受的是this对象,call第二个参数以后可以接受字符串形式的参数,apply接受的是一个类数组/数组参数

将null || undefined作为this的绑定对象传入call/apply/bind时,这些值在调用时会被忽略,实际应用的是默认绑定规则

2.4 new绑定

JavaScript语言中的new操作符和其他面向对象语言中的new操作符不大一样,因为在JavaScript中没有对象的概念。所有的函数都可以使用new来调用,new的调用又称为构造函数调用。在构造函数调用过程中,会自动执行下面的操作。

1、创建(或者说构造)一个全新的对象

2、这个对象会被执行[[Prototype]]连接

3、这个新对象会绑定到函数调用的this

4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象

构造函数也是js中常用的一种设计模式,如以下代码:

function Test(a, b) {
       this.a = a;
       this.b = b;
       this.add = function() {
         debugger;
        console.log(this.a + this.b);
       }
    }
    var cc = new Test(1, 2);
    cc.add();
    console.log(cc);

在new调用过程中,返回了一个新对象,并且该对象的this指向Test;

时间: 2019-03-15

vue项目中在外部js文件中直接调用vue实例的方法比如说this

一般我们都是在main.js中引入vue,然后在vue文件中直接使用this(this指向的是vue实例),但是在实际开发中,我们往往会引入外部的js文件使用this,这个this就会指向window,并不是我们期待的vue实例,那么就需要重新引入vue文件(import Vue from 'vue'),这样很麻烦.在目前项目中我使用的方法是mian.js导出vue实例,然后在需要使用的js中引入. 步骤一:main.js导出vue实例 var vue = new Vue({ el: '#app

javascript的this关键字详解

this 的定义 表示当前执行代码的环境对象 因此可将 this 的剖析分为"全局环境" 和 "函数环境" 两种类型的环境对象 全局环境 console.log(this === window); // true var a = 10; console.log(this.a); // 10 函数环境 在函数内部,this 的取值取决于函数被调用时的运行环境. 这里涉及到内存里的数据结构相关的知识点,当我们定义以下字面量对象时会发生一系列的关联关系 var obj =

JS匿名函数内部this指向问题详析

前言 网上看到一句话,匿名函数的执行是具有全局性的,那怎么具有的全局性呢? this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到底指向谁,实际上this的最终指向的是那个调用它的对象 1.案例中,第一个say打出来的是Alan,而第二个则是window var name = 'window' var person = { name :'Alan', sayOne:function () { console.log(this.name) }, sayTwo:functi

Javascript的this详解

在理解javascript的this之前,首先先了解一下作用域. 作用域分为两种: 1.词法作用域:引擎在当前作用域或者嵌套的子作用域查找具有名称标识符的变量.(引擎如何查找和在哪查找.定义过程发生在代码书写阶段) 2.动态作用域:在运行时被动态确定的作用域. 词法作用域和动态作用域的区别是:词法作用域是在写代码或定义时确定的:动态作用域是在运行时确定的. this的绑定规则 this是在调用时被绑定,取决于函数的调用位置.由此可以知道,一般情况下(非严格模式下),this都会根据函数调用(调用

JavaScript箭头函数中的this详解

前言 箭头函数极大地简化了this的取值规则. 普通函数与箭头函数 普通函数指的是用function定义的函数: var hello = function () { console.log("Hello, Fundebug!"); } 箭头函数指的是用=>定义的函数: var hello = () => { console.log("Hello, Fundebug!"); } JavaScript箭头函数与普通函数不只是写法上的区别,它们还有一些微妙的不

JavaScript中this的全面解析及常见实例

前言 this 关键字在 Javascript 中非常常见,但是很多开发者很难说清它到底指向什么.大部分人会从字面意思上去理解 this,认为 this 指向函数自身,实际上this 是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决于函数调 用时的各种条件.this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式. 总结: 函数被调用时发生 this 绑定,this 指向什么完全取决于函数在哪里被调用. 一.this 的绑定规则 this 一共有 4 中绑定规则,接下来一一介

详解JavaScript中关于this指向的4种情况

对很多前端开发者来说,JavaScript语言的this指向是一个令人头疼的问题.先看下面这道测试题,如果你能实现并解释原因,那本文对你来说价值不大,可以直接略过. **开篇测试题:**尝试实现注释部分的Javascript代码,可在其他任何地方添加更多代码(如不能实现,说明一下不能实现的原因): let Obj = function (msg) { this.msg = msg this.shout = function () { alert(this.msg) } this.waitAndS

JavaScript this绑定过程深入详解

本文实例形式详细分析了JavaScript this绑定过程.分享给大家供大家参考,具体如下: 在理解this 的绑定过程之前,首先要理解调用位置:调用位置就是函数在代码中被调用的位置(而不是声明的位置).只有仔细分析调用位置才能回答这个问题:这个this 到底引用的是什么?通常来说,寻找调用位置就是寻找"函数被调用的位置",但是做起来并没有这么简单,因为某些编程模式可能会隐藏真正的调用位置.最重要的是要分析调用栈(就是为了到达当前执行位置所调用的所有函数).我们关心的调用位置就在当前

对Vue.js之事件的绑定(v-on: 或者 @ )详解

1.Vue.js事件绑定的一般格式 v-on:click='function' v-on:click/mouseout/mouseover/ @click 2.Vue.js事件绑定的实现 2.1 JavaScript代码 <script type="text/javascript" src="../js/vue-1.0.21.js"></script> <script type="text/javascript"&g

从表单校验看JavaScript策略模式的使用详解

众所周知的是,表单确实在前端,唔,或者说在网页中占有不小的比重.事实上,几乎每一个中大型网站都会有"登录注册"以验证用户信息.防止一些不可名状的隐患... 那么表单的优劣就成了前端开发者急需解决的问题.其实我更愿意称为"代码的可读性"或"可复用性"以及"是否冗杂". 表单也有"优劣"?你在开玩笑嘛? 我想你可以认真看下下面的代码,它用到了一些"新知识": <form action=

JavaScript编写棋盘覆盖代码详解

一.前言 之前做了一个算法作业,叫做棋盘覆盖,本来需要用c语言来编写的,但是因为我的c语言是半桶水(哈哈),所以索性就把网上的c语言写法改成JavaScript写法,并且把它的覆盖效果显示出来 二.关键代码 <!DOCTYPE html> <html> <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <titl

javascript 正则表达式分组、断言详解

 javascript 正则表达式分组.断言详解 提示:阅读本文需要有一定的正则表达式基础. 正则表达式中的断言,作为高级应用出现,倒不是因为它有多难,而是概念比较抽象,不容易理解而已,今天就让小菜通俗的讲解一下. 如果不用断言,以往用过的那些表达式,仅仅能获取到有规律的字符串,而不能获取无规律的字符串. 举个例子,比如html源码中有<title>xxx</title>标签,用以前的知识,我们只能确定源码中的<title>和</title>是固定不变的.因

javascript中Array()数组函数详解

在程序语言中数组的重要性不言而喻,JavaScript中数组也是最常使用的对象之一,数组是值的有序集合,由于弱类型的原因,JavaScript中数组十分灵活.强大,不像是Java等强类型高级语言数组只能存放同一类型或其子类型元素,JavaScript在同一个数组中可以存放多种类型的元素,而且是长度也是可以动态调整的,可以随着数据增加或减少自动对数组长度做更改. Array()是一个用来构建数组的内建构造器函数.数组主要由如下三种创建方式: array = new Array() array =

Javascript 实现计算器时间功能详解及实例(二)

Javascript 计算器: 系列文章: JS 实现计算器详解及实例代码(一) Javascript 实现计算器时间功能详解及实例(二) Javascript计算器 -> 添加时间在屏显区左上角添加时间显示 效果图如下: 代码 初始化 // 计算器初始化 Calculator.prototype.init = function () { this.addTdClick(); // 时间显示 this.showDate(); }; 时间显示 // 在屏显区左上角显示时间日期 Calculator

玩转JavaScript OOP - 类的实现详解

概述 当我们在谈论面向对象编程时,我们在谈论什么? 我们首先谈论的是一些概念:对象.类.封装.继承.多态. 对象和类是面向对象的基础,封装.继承和多态是面向对象编程的三大特性. JavaScript提供了对象却缺乏类,它不能像C#一样能显式地定义一个类. 但是JavaScript的函数功能非常灵活,其中之一就是构造函数,结合构造函数和原型对象可以实现"类". 对象和类的概念 对象 "对象"是面向对象编程中非常重要的一个概念,一个对象是一个"东西"

JavaScript中eval()函数用法详解

eval() 函数计算 JavaScript 字符串,并把它作为脚本代码来执行. 如果参数是一个表达式,eval() 函数将执行表达式.如果参数是Javascript语句,eval()将执行 Javascript 语句. 语法 复制代码 代码如下: eval(string) 参数 描述 string 必需.要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句. eval()函数用法详解: 此函数可能使用的频率并不是太高,但是在某些情况下具有很大的作用,下面就介绍一下eva

Javascript 严格模式use strict详解

严格模式:由ECMA-262规范定义的JavaScript标准,对javascrip的限制更强. (非严格的模式,被称为"马虎模式/稀松模式/懒散模式".) 一.严格模式的使用 严格模式可以在脚本或函数级别实现.(即全局和局部模式) 1.全局 在js文件的最前面添加    "use strict" 2.局部 在函数内部添加   "use strict",如下 function fn() { "use strict"; //so