总结this的3个规则:

  1. this是调用上下文,上下文被创建或者初始化时才确定
  2. 非严格模式:this是全局对象;严格模式:this是undefined
  3. 函数调用

    a. 以函数形式调用的函数通常不使用this关键字,非严格模式下函数调用模式的this就是全局对象。

    b. 以方法形式调用的函数的this指的是当前调用方法的对象

    c. 以构造函数形式调用的函数的this指的是被构造的对象,具体操作为:

      i. 创建一个新对象

      ii. 将构造函数的作用域赋给新对象(因此构造函数中的this就指向这个新对象)

      iii. 执行构造函数的代码(为这个新对象添加属性,这个时候this才确定下来就是该对象)

      iv. 返回新对象

      v. 另外要注意的是,构造函数通常不使用return关键字,如果使用,则调用表达式的值就是return的这个对象,如果使用却没有指定返回值,或者返回一个原始值,那么就忽略返回        值,同时使用构造出来的新对象作为返回结果。

  4. this是一个关键字,js的语法不允许给this赋值,关键字this没有作用域的限制,嵌套的函数不会从调用它的函数中继承this。即:如果嵌套函数作为方法调用,其this的值指向调用它的对象(与规则3相符合)

如果嵌套函数作为函数调用,其this的值不是全局对象(非严格模式)就是undefined(严格模式)。(与规则2、3符合)

例子:嵌套函数访问外部函数的this(来自《javascript权威指南》P171)

var o={                                    //对象o
  m:function(){ //对象中的方法m()
  var self=this; //将this的值保存至一个变量中
  console.log(this===o); //输出true,this就是这个对象
  f(); //调用辅助函数f()(此时调用外部函数的m()时此处的f()调用嵌套函数就属于函数调用了)   function f(){ //定义一个嵌套函数
    console.log(this===o);       //"false":this的值是全局对象或者undefined;
    console.log(self===o);       //"true":self指外部函数的this值
  } }

  5. 构造函数的原型模式中的this

   如果要在基本包装类型String添加了一个名为startsWith()的方法。 

String.prototype.startsWith=function(text){
  return this.indexOf(text)==0;
} var msg="hello world";
alert(msg.startsWith("Hello")); //true

这里的原型函数中的this也是指向调用者的,要知道prototype中的这些方法和属性是所有实例对象所共享的,也就是说当新创建的对象msg以方法调用模式调用startsWith()方法,虽然在实例中没有找到这个方法,但在原型对象中找到了这个方法,故返回的就是这个方法的值,注意,在原型中查找值的过程是一次过程。

  6. 匿名函数中的this

  匿名函数属于函数表达式,不能变量提升,函数表达式必须等到js引擎执行到它所在行时,才会从上而下一行一行地解析,匿名函数的执行环境具有全局性,因此其this对象通常指向window,来看( function(){…} )()和( function (){…} () )这两种立即执行函数的写法,要知道在函数体后面加括号就能立即调用,则这个函数必须是函数表达式,不能是函数声明。

  这样的写法有什么用呢?

javascript中没用私有作用域的概念,如果在多人开发的项目上,你在全局或局部作用域中声明了一些变量,可能会被其他人不小心用同名的变量给覆盖掉,根据javascript函数作用域链的特性,可以使用这种技术可以模仿一个私有作用域,用匿名函数作为一个“容器”,“容器”内部可以访问外部的变量,而外部环境不能访问“容器”内部的变量,所以( function(){…} )()内部定义的变量不会和外部的变量发生冲突,俗称“匿名包裹器”或“命名空间”。

例子:

  • 箭头函数中的this
let name='windows';
let obj={
  name:'windows',
  stack: () => {
    console.log(this.name); //undefine
  }
}
console.log(obj.stack()); //undefine

说明:箭头函数表达式的语法比函数表达式更短,并且没有自己的this,arguments,super或者new.target。这些函数表达式更适用于那些本来需要匿名函数的地方,并且它们不能用作构造函数。箭头函数不会创建自己的this,它只会从作用链的上一层继承this。

function Stack() {
  this.age = 0;
  setInterval(() => {
    this.age++; // this正确地指向Stack对象
  }, 1000);
}
var p = new Stack();
console.log(p.age);

箭头函数不能用作构造器,和new一起会抛出错误

let Foo = () => {};
let foo = new Foo(); // TypeError: Foo is not a constructor let Stack=()=> {
  let name='outside';
  class Stack{
    constructor(){
      this.name=name;
    }
  }
  return Stack;
};
let b=new Stack();
console.log(b.name);//Stack is not a constructor let Stack = () => {
  let name = 'outside';
  console.log(this);
  class Stack {
    constructor() {
      this.name = name;
    }
  }
  return Stack;
};
console.log(new Stack().name); //Stack is not a constructor

箭头函数没有prototype属性

let Foo = () => {};
console.log(Foo.prototype); // undefined
  • 箭头函数用于闭包
let Stack = () => {
  let name = 'outside';
  console.log(this);//Window
  class Stack {
    constructor() {
      //this.name = 'inside';
      this.name = name;
    }
  }
  return new Stack();
};
console.log(Stack().name);//outside
let Stack = () => {
  let name = 'outside';
  console.log(this);//Window
  class Stack {
    constructor() {
      this.name = 'inside';
    }
  }
  return Stack;
};
console.log(Stack().name);//Stack
  • 匿名函数用于闭包
let Stack = function() {
  let name = 'outside';
  console.log(this);//Window
  class Stack {
    constructor() {
      this.name = name;
    }
  }
  return Stack;
}();
let b = new Stack();
console.log(b.name);//outside let Stack = function() {
  let name = 'outside';
  console.log(this);//Window
  class Stack {
    constructor() {
      this.name = name;
    }
  }
  return Stack;
};
//let b = new Stack();
let b = Stack();
let a=new b();
console.log(a.name);//outside

javascript当中的this详解的更多相关文章

  1. JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解

    二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...

  2. (转)javascript中event对象详解

    原文:http://jiajiale.iteye.com/blog/195906 javascript中event对象详解          博客分类: javaScript JavaScriptCS ...

  3. Javascript 异步加载详解

    Javascript 异步加载详解 本文总结一下浏览器在 javascript 的加载方式. 关键词:异步加载(async loading),延迟加载(lazy loading),延迟执行(lazy ...

  4. 【JavaScript中的this详解】

    前言 this用法说难不难,有时候函数调用时,往往会搞不清楚this指向谁?那么,关于this的用法,你知道多少呢? 下面我来给大家整理一下关于this的详细分析,希望对大家有所帮助! this指向的 ...

  5. JavaScript中的this详解

    前言 this用法说难不难,有时候函数调用时,往往会搞不清楚this指向谁?那么,关于this的用法,你知道多少呢? 下面我来给大家整理一下关于this的详细分析,希望对大家有所帮助! this指向的 ...

  6. Javascript中prototype属性详解 (存)

    Javascript中prototype属性详解   在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不 ...

  7. Javascript常用的设计模式详解

    Javascript常用的设计模式详解 阅读目录 一:理解工厂模式 二:理解单体模式 三:理解模块模式 四:理解代理模式 五:理解职责链模式 六:命令模式的理解: 七:模板方法模式 八:理解javas ...

  8. JavaScript 各种遍历方式详解及总结

    JavaScript 各种遍历方式详解 在$.each中想要终止循环,但是它没有continue或者break这样的终止方式,所以尝试使用return来进行终止,但是发现并没有跳出循环.为了搞清楚js ...

  9. JavaScript进阶内容——DOM详解

    JavaScript进阶内容--DOM详解 当我们已经熟练掌握JavaScript的语法之后,我们就该进入更深层次的学习了 首先我们思考一下:JavaScript是用来做什么的? JavaScript ...

随机推荐

  1. Coding and Paper Letter(四十五)

    资源整理. 1 Coding: 1.Python库gempy,一种基于Python的开源三维结构地质建模软件,它允许从界面和方向数据隐式(即自动)创建复杂的地质模型. 它还支持随机建模以解决参数和模型 ...

  2. Mybatis笔记四:nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'id' in 'class java.lang.String'

    错误异常:nested exception is org.apache.ibatis.reflection.ReflectionException: There is no getter for pr ...

  3. 【BZOJ3162】独钓寒江雪(树哈希,动态规划)

    [BZOJ3162]独钓寒江雪(树哈希,动态规划) 题面 BZOJ 题解 忽然翻到这道题目,突然发现就是前几天一道考试题目... 题解: 树哈希,既然只考虑这一棵树,那么,如果两个点为根是同构的, 他 ...

  4. 解决:LNMP架构下访问php页面出现500错误

    默认情况下,如果被访问的php脚本中包含语法错误,服务器会返回一个空的“200 ok”页面 在php.ini中的fastcgi.error_header选项允许在这种情况下产生一个HTTP错误码 以使 ...

  5. Linux基础------文件打包解包---tar命令,文件压缩解压---命令gzip,vim编辑器创建和编辑正文件,磁盘分区/格式化,软/硬链接

    作业一:1) 将用户信息数据库文件和组信息数据库文件纵向合并为一个文件/1.txt(覆盖) cat /etc/passwd /etc/group > /1.txt2) 将用户信息数据库文件和用户 ...

  6. move_base的全局路径规划代码研究

    algorithmn parameter code 主要是以下三个函数 计算所有的可行点 怎么计算一个点的可行点 从可行点中计算路径path todo algorithmn 算法的解释 Dijkstr ...

  7. JSP2 的自定义标签

    在 JSP 中开发标签库只需如下几个步骤 1.开发自定义标签处理类 2.建立一个 *.tld 文件,每个 *.tld 文件对应一个标签库,每个标签库可包含多个标签 3.在 JSP 文件中使用自定义标签 ...

  8. 改变你一生的编辑器:VSCode使用总结

    开发十年,只剩下这套Java开发体系了 >>>   前言:vscode是微软出品的,基于Electron和TypeScript的,现在已经是最火的一款文本编辑器.我认为vscode是 ...

  9. Linux下如何卸载软件(Debian系)

    说明:此方法适用于Debian.Ubuntu等带apt工具的操作系统. 步骤: 1.首先我们需要知道将要卸载的软件名称,比如我现在打算卸载tightvncserver,但是如果你不确定名称,没关系,可 ...

  10. 【AtCoder】ARC092 D - Two Sequences

    [题目]AtCoder Regular Contest 092 D - Two Sequences [题意]给定n个数的数组A和数组B,求所有A[i]+B[j]的异或和(1<=i,j<=n ...