日常开发中,我们经常用到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. 微信小程序开发常用方法

    1.函数中访问data中的数据 _this.setData({ // 日历数据 signList: dataList, // 当前日期 todayDay: str }) 2.if判断 wx:if=&q ...

  2. drf05 路由Routers

    对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息. REST framework提供了两个router ...

  3. 【转载】Intellij IDEA的Hibernate简单应用

    转载自: https://www.cnblogs.com/yangyquin/p/5438248.html   1.创建数据库及其表 create database demo;    use demo ...

  4. Day 25 面向对象

    面向对象基础 面向对象编程 面向过程编程:类似于工厂的流水线 优点:逻辑清晰 缺点:扩展性差 面向对象编程:核心是对象二字,对象属性和方法的集合体,面向对象编程就是一堆对象交互 优点:扩展性强 缺点: ...

  5. 编写 Shell 脚本的最佳实践

    转自:http://kb.cnblogs.com/page/574767/ 前言 由于工作需要,最近重新开始拾掇shell脚本.虽然绝大部分命令自己平时也经常使用,但是在写成脚本的时候总觉得写的很难看 ...

  6. Python——Numpy基础知识(一)

    一.Numpy的引入 1.标准的Python 中用列表(list)保存一组值,可以当作数组使用.但由于列表的元素可以是任何对象,因此列表中保存的是对象的指针.对于数值运算来说,这种结构显然比较浪费内存 ...

  7. 51nod1183 编辑距离【动态规划】

    编辑距离,又称Levenshtein距离(也叫做Edit Distance),是指两个字串之间,由一个转成另一个所需的最少编辑操作次数.许可的编辑操作包括将一个字符替换成另一个字符,插入一个字符,删除 ...

  8. [luogu4285 SHOI2008] 汉诺塔 (暴力,数学)

    传送门 Solution 强行猜测公式形如\(f_i=k\times f_{i-1}+b\),暴力求\(f_1,f_2,f_3\),剩下的递推就行 Code #include <cstdio&g ...

  9. Firefly-rk3399 开发板环境搭建

    Firefly教程网站:http://wiki.t-firefly.com/zh_CN/Firefly-RK3399/started.html 系统烧录: http://wiki.t-firefly. ...

  10. ls命令:显示文件或目录

    ls:显示目录下的内容及相关属性信息 [命令详解] [功能说明] ls命令可以理解为英文list的缩写,其功能是列出目录的内容及其内容属性信息(list directory contents).该命令 ...