日常开发中,我们经常用到this。一开始常会用一种感觉去判断this的指向,当遇到复杂的函数调用时,就分不清this的指向。

今天我们来由浅入深来学习下。

function family1(){
var name = "小白";
console.log(this); //Window
console.log(this.name); //undefined
}
family1(); // 等同于 window.family()

this指向的是调用它的对象,family处于全局,等同于 window.family(),此刻this等同于由window调用的, window中不存在name, 故为undefined

函数作为对象的一个属性

var family2 = {
name:"小白",
fn:function(){
console.log(this.name); //小白
}
}
family2.fn();

this指向的是对象family2,因为fn不仅作为一个对象family2的一个属性,而且是作为对象的一个属性被调用,即通过family2.fn()执行的。结果this就是对象family2。

var family2 = {
name:"小白",
fn:function(){
     console.log(this) //window
console.log(this.name); //undefined
}
}
var newfn = family2.fn();
newfn();

如果fn函数被赋值到了另一个变量newfn中,并没有作为family2的一个属性被调用,那么this的值就是window,this.name为undefined。

构造函数中this,new实例化

如果函数作为构造函数用,那么其中的this就代表它即将new出来的对象。

function Fn(){
this.name = "小白",  
   console.log(this)
}
var family3 = new Fn();
console.log(family3.name); //小白

因为new关键字可以改变this的指向,将这个this指向对象family3, 变量family3创建了一个Fn的实例(相当于复制了一份Fn到对象family3里面),此时仅仅只是创建,并没有执行,而调用这个函数Fn的是对象family3,那么this指向的自然是对象family3,那么为什么对象family3中会有name,因为你已经复制了一份Fn函数到对象a中,用了new关键字就等同于复制了一份。

    function Fn(){
this.name = "小白",
console.log(this) // window
}
Fn()

函数用call或者apply调用

当一个函数被call和apply调用时,this的值就取传入的对象的值。

我们通过几道题来练练手吧。

    var a=11
function test1(){
this.a=22;
console.log(this); //window,此时通过this修改了全局变量a的值,由11为22
let b = function(){
console.log(this); //window
console.log(this.a); //
};
b();
}
test1();
 var a=11
function test1(){
console.log(this) // function test1()
this.a=22; // 相当于给test1函数添加了 var a = 22
let b=function(){
console.log(this) //window
console.log(this.a); //
};
b();
}
var t = new test1();

以下几题进行对比

        var val = 1;
var obj = {
val: 3,
fun: function () {
console.log(val); //
this.val *= 2;
//this指向window,故window里面的window.val = val*2
console.log(val); //
val *= 2;
//指window, window.val = val * 2
console.log(val); // 4 在 this.val *= 2的基础上再 val*2
console.log(this.val); //
}
};
var objFun = obj.fun;
objFun(); // 1 2 4 4
      var val = 1;
var obj = {
val: 3,
fun: function () {
this.val *= 2; //this指向obj,故obj里面的obj.val = val*2
console.log(val); //
val *= 2; //指window, window.val = val * 2
console.log(val);// 此时val为1; 即 1*2
console.log(this.val); // this为obj; 此时val为3;即3*2
}
};
obj.fun(); // 1 2 6
        var val = 1;
var obj = {
val: 3,
fun: function () {
this.val *= 2;
console.log(val); //
val *= 2;
console.log(val);//
console.log(this.val); // this为obj; 此时val为3;即3*2
}
};
obj.fun(); // 1 2 6
var objFun = obj.fun; // 此时初始化window.val = 2; obj.val = 6
objFun(); // 4 8 8 注: 第一次调用后obj.fun影响第二次调用objFun

以下两个例子对比

      var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
console.log(this) // obj
var that = this;
return function(){
console.log(that) //obj
return that.name;
};
}
};
console.log(object.getNameFunc()()); //My Object
    var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
console.log(this) // obj
return function(){
console.log(this) //window
return this.name;
};
}
};
console.log(object.getNameFunc()()); //The Window
object.getNameFunc()返回的是一个匿名函数,匿名函数的this是window

以下是英文原文:

Anonymous functions are not bound to an object in this context, meaning the this object points to window unless executing in strict mode (where this is undefined).

翻译:在这个上下文(执行环境)中匿名函数并没有绑定到任何一个对象中,意味着this指向window

(除非这个上下文(执行环境)是在严格模式‘use strict’下执行的,而严格模式下该this指向undefined)

大白话理解this的更多相关文章

  1. 大白话理解cookie

    HTTP协议是一个无状态的协议,服务器无法区分出两次请求是否发送自同一服务器. 需要通过会话控制来解决这个问题,会话控制主要有两种方式Cookie 和 Session. Cookie就是一个头,Coo ...

  2. 大白话理解promise对象

    Promise  代表了未来某个将要发生的事件(通常是一个异步操作)  Promise 是异步编程的解决方案,能够简化多层回调嵌套,代表了未来某个将要发生的事件.Promise是一个构造函数,本身有a ...

  3. 大白话理解箭头函数this

    var obj1={ num:4, fn:function(){ num:5; var f=() => { num:6; console.log(this.num); //4 外层非箭头函数包裹 ...

  4. 【Hibernate框架】关联映射(一对一关联映射)

    一.整理思路: 之前,小编总结过Mybatis的关联映射,接下来,再来总结一下hibernate的相关的关联映射,直接上图: 这张图,就是小编整理总结整个Hibernate的关联映射的一个大致思路. ...

  5. Block、委托、回调函数原理剖析(在Object C语境)——这样讲还不懂,根本不可能!

    开篇:要想理解Block和委托,最快的方法是搞明白“回调函数”这个概念. 做为初级选手,我们把Block.委托.回调函数,视为同一原理的三种不同名称.也就是说,现在,我们把这三个名词当成一回事.在这篇 ...

  6. Git使用教程之SSH连接方式配置(二)

    什么是GitHub?这个网站就是提供Git仓库托管服务的. 什么是SSH Key?你的本地Git仓库和GitHub仓库之间的传输是通过SSH加密的,大白话理解就是这两个仓库如果要进行远程同步,则我们需 ...

  7. Java 复习整理day05

    1 package com.it.demo01_oop; 2 3 import java.util.Arrays; 4 5 /* 6 案例: 演示面向过程和面向对象代码的区别 7 8 面向过程编程思想 ...

  8. Java复习整理 Day02

    1 package demo01; 2 3 import java.util.Scanner; 4 5 public class ScannerDemo01 { 6 public static voi ...

  9. pycharm的基本使用 、 Python的注释语法,变量,常量,垃圾回收机制,数据类型

    1.文件路径要注意 我把文件放在了D盘,如下图:你们可以根据自身情况设置 2.python环境要选择本地下载好的 如下图: 点击本机存在的环境,如果提示NO interpr,就点击第二步 如果还是没有 ...

随机推荐

  1. vue移动端Ui组件 mint-ui 使用指南

    1.上啦加载下拉刷新的使用 this.$refs.loadmore.onTopLoaded(); this.$refs.loadmore.onBottomLoaded(); 上啦刷新下拉加载的 动画显 ...

  2. js通过插件发送邮件

    这个插件为SmtpJS 官网地址为  https://www.smtpjs.com/ 方法很简单 <script src="https://smtpjs.com/v2/smtp.js& ...

  3. drf04 drf视图类

    REST framework 提供了众多的通用视图基类与扩展类,以简化视图的编写. 1.2个视图基类 1.1. APIView rest_framework.views.APIView APIView ...

  4. 5.win上安装ES

    安装步骤如下: 1.安装JDK 至少1.8.0_73以上版本,使用 java -version 这个命令进行查看java的版本 2.下载和解压缩Elasticsearch安装包, 解压后目录结构: 3 ...

  5. 在vue项目中引用element-ui时 让el-input 获取焦点的方法

    在制作项目的时候遇到一个需求,点击一个按钮弹出一个input输入框,并让输入框获得焦点,项目中引用了ElementUI 在网上查找了很多方法,但是在实际使用中发现了一个问题无论是使用$ref获取inp ...

  6. Bootstrap关于表单控件(按扭)

    按钮也是表单重要控件之一,制作按钮通常使用下面代码来实现:   ☑  input[type=“submit”]   ☑  input[type=“button”]   ☑  input[type=“r ...

  7. (33)Spring Boot 监控和管理生产环境【从零开始学Spring Boot】

    [本文章是否对你有用以及是否有好的建议,请留言] spring-boot-actuator模块提供了一个监控和管理生产环境的模块,可以使用http.jmx.ssh.telnet等拉管理和监控应用.审计 ...

  8. vs--bookmark用法

    快捷键 Ctrl+K,K 增加/取消书签 Ctrl+K,P 导航到上一个书签 Ctrl+K,N 导航到下一个标签 Ctrl+K,L 取消所有书签

  9. boost中的有用工具assign和uuid

    assign assign重载'+'=和','实现连续赋值 assign不仅支持所有8个STL标准容器(vector.string.deque.list.set.multiset.map.multim ...

  10. hdu5389 Zero Escape DP+滚动数组 多校联合第八场

    Zero Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others) To ...