博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
js中this的指向问题
阅读量:5228 次
发布时间:2019-06-14

本文共 2965 字,大约阅读时间需要 9 分钟。

在浏览器的全局环境中,严格和非严格模式的this都指向window;而在函数执行环境中,this的指向不是在函数定义的时候确定的,而是在函数执行的时候确定。

函数调用的几种方式:

  a、普通函数调用

  b、作为方法来调用

  c、作为构造函数来调用

  d、使用apply/call/bind方法来调用

  e、匿名函数调用

  f、es6中的箭头函数调用

总结一句话:在函数执行的时候,谁调用这个函数或者方法,那么this就指向谁。下面就这6种在浏览器环境下逐一分析,同时考虑严格模式和非严格模式的情况。

1、普通函数调用

// "use strict";  function say() {    console.log(this);  }  say(); // 输出: Window 严格模式下:undefined

这里的say()在非严格模式下等于:window.say();而在严格模式下,你可以想象成:undefined.say(),所以this指向undefined

2、作为方法来调用

// "use strict";  let username = 'liutt';  let person = {    username: 'liuhw',    say: function () {      console.log(this.username);    }  };  person.say(); // 严格和非严格模式都输出:liuhw  let say = person.say;  say(); // 输出:undefined,let属于块级作用域,所以window.username 未声明,严格模式下 Uncaught TypeError: Cannot read property 'username' of undefined

person作为一个对象实例,通过点语法调用say(),所以this指向person;因为做了变量赋值,所以最后一行say()就相当于作为普通函数调用,在严格模式下,因为this指向undefined,所以this.username就抛异常了

3、作为构造函数来调用

// "use strict";  function Person(username) {    this.username = username  }  let person = Person('liuhw');  console.log(person.username); // 非严格和严格模式都抛异常  console.log(window.username); // 非严格模式:liuhw,严格模式构造函数抛异常

非严格模式下Person('liuhw')等于window.Person('liuhw'),函数没有返回值,所以person为undefined,导致person.username抛异常

严格模式下Person('liuhw')等于undefined.Person('liuhw'),this指向undefined,导致构造函数中的this.username抛异常

// "use strict";  function Person(username) {    this.username = username  }  let person = new Person('liuhw');  console.log(person.username); // 非严格和严格模式:liuhw  console.log(window.username); // 非严格和严格模式:undefined

 4、使用apply/call/bind方法来调用

// "use strict";  let username = 'liutt';  let person = {    username: 'liuhw',    say: function () {      console.log(this.username);    }  };  person.say.apply(); // 输出:undefined 严格模式:抛异常  person.say.call(); // 输出:undefined 严格模式:抛异常  person.say.bind()(); // 输出:undefined 严格模式:抛异常  person.say.apply(person); // 非严格和严格模式都输出:liuhw  person.say.call(person); // 非严格和严格模式都输出:liuhw  person.say.bind(person)(); // 非严格和严格模式都输出:liuhw

call、apply和bind可以改变this的指向,都指向它们的第一个参数,如果第一个参数为空,则默认为全局对象window

bind跟前两者有点区别,bind只是做个绑定,返回对应函数,而call和apply则立即调用函数,所以想要达到同样的目的,bind后面还得加上一对括号,表示立即调用返回的函数

5、匿名函数调用

// "use strict";  var username = 'liutt';  let person = {    username: 'liuhw',    printUsername: function() {      console.log(this.username);    },    say: function () {      (function (callback) {        callback();      })(this.printUsername);    }  };  person.say(); // 非严格模式:liutt,严格模式:抛异常

在当前这个执行环境中匿名函数并没有绑定到任何一个对象上,所以this指向window,严格模式下this指向undefined

6、es6中的箭头函数调用

// "use strict";  var username = 'liutt';  setTimeout(() => {    console.log(this.username) // 严格和非严格模式:liutt  });  function Person() {    this.username = 'liuhw';    setTimeout(() => {      console.log(this.username);    })  }  new Person(); // 严格和非严格模式:liuhw

箭头函数没有自己的this,它的this是继承自定义它的宿主对象,或者说是外部对象,如代码所示,第一个setTimeout中的箭头函数的宿主对象是window,第二个则是new Person(),所以经常遇到箭头函数多层嵌套,它们的this都是从最外层的宿主对象一层层继承下去。

转载于:https://www.cnblogs.com/liuhw/p/10648432.html

你可能感兴趣的文章
pwershell switch 语句
查看>>
学习Spring Boot:(五)使用 devtools热部署
查看>>
三人行有我师?取长补短?影响力?
查看>>
设计模式——设计模式概述
查看>>
封装一个获取module.exports内容的方法
查看>>
动态连接库
查看>>
ServletContext 与application的异同
查看>>
水平垂直居中
查看>>
CSS3教程:border-image属性
查看>>
asp.netmvc常见功能链接
查看>>
sql server系统表详细说明
查看>>
SQL Server 2008连接字符串写法大全
查看>>
sql server 使用链接服务器远程查询
查看>>
JavaScript中的继承
查看>>
MySQL简介
查看>>
设计模式之桥接模式(Bridge)
查看>>
转:探讨跨域请求资源的几种方式
查看>>
jquery的$(document).ready()和onload的加载顺序
查看>>
Python Web框架Django (五)
查看>>
.net学习之继承、里氏替换原则LSP、虚方法、多态、抽象类、Equals方法、接口、装箱拆箱、字符串------(转)...
查看>>