js this
来源:互联网 发布:tensorflow论坛 编辑:程序博客网 时间:2024/06/08 09:10
上周发的闭包,这周说下与闭包相关的this,this同样是面试必问的话题,我这里就我的理解结合高程阐述一下。
定义:this是在执行上下文创建时确定的一个在执行过程中不可更改的变量。
所谓执行上下文,就是JavaScript引擎在执行一段代码之前将代码内部会用到的一些变量、函数、this提前声明然后保存在变量对象中的过程。这个’代码片段’包括:全局代码(script标签内部的代码)、函数内部代码、eval内部代码。而我们所熟知的作用域链也会在保存在这里,以一个类数组的形式存储在对应函数的[[Scopes]]属性中。
this只在函数调用阶段确定,也就是执行上下文创建的阶段进行赋值,保存在变量对象中。这个特性也导致了this的多变性:即当函数在不同的调用方式下都可能会导致this的值不同。
一.一般情况
1.全局函数中,严格模式下指向undefined,非严格模式下指向window
2.某个对象调用方法时,this指向这个对象
3.谁调指向谁
var b = 1;function fun() { 'use strict'; var b = 2; return this.b;}fun();//报错 Cannot read property 'b' of undefined
var a = 1;function fun() { var a = 2; return this.a;}fun();//1
var a = 1;var obj = { a: 2, b: function() { return this.a; }}console.log(obj.b())//2
var a = 1;var obj = { a: 2, b: function() { return this.a; }}var t = obj.b;console.log(t());//1相当于window.t()
注意:当函数独立调用的时候,在严格模式下它的this指向undefined,在非严格模式下,当this指向undefined的时候,自动指向全局对象(浏览器中就是window),高程中解释:匿名函数的执行环境为全局环境
var a = 1;var obj = { a: 2, b: function () { function fun() { return this.a } console.log(fun()); }} obj.b();//1
注意:当obj在全局声明的时候,obj内部属性中的this指向全局对象,当obj在一个函数中声明的时候,严格模式下this会指向undefined,非严格模式自动转为指向全局对象。
var a = 1000;var obj = { a: 1, b: this.a + 1}function fun() { var obj = { a: 1, c: this.a + 2 //严格模式下这块报错 Cannot read property 'a' of undefined } return obj.c;}console.log(fun());//1002console.log(obj.b);//1001
二.使用apply,call
关于apply和call是干什么的怎么用本文不涉及,请移驾:apply,call
这是个万能公式,实际上上面直接调用的代码,我们可以看成这样的:
function fun() { return this.a;}fun();//1//严格模式fun.call(undefined)//非严格模式fun.call(window)
这时候我们就可以解释下,为啥说在非严格模式下,当函数this指向undefined的时候,会自动指向全局对象,如上,在非严格模式下,当调用fun.call(undefined)的时候打印出来的依旧是1,就是最好的证据。
为啥说是万能公式呢?再看函数作为对象的方法调用:
var a = 1;var obj = { a: 2, b: function() { return this.a; }}obj.b()obj.b.call(obj)
如上,是不是很强大,可以理解为其它两种都是这个方法的语法糖罢了,那么apply和call是不是真的万能的呢?并不是,ES6的箭头函数就是特例,因为箭头函数的this不是在调用时候确定的,这也就是为啥说箭头函数好用的原因之一,因为它的this固定不会变来变去的了。关于箭头函数的this我们稍后再说。
三作为构造函数
何为构造函数?所谓构造函数就是用来new对象的函数,像Function、Object、Array、Date等都是全局定义的构造函数。其实每一个函数都可以new对象,那些批量生产我们需要的对象的函数就叫它构造函数罢了。注意,构造函数首字母记得大写。
function Fun() { this.name = 'Damonre'; this.age = 21; this.sex = 'man'; this.run = function () { return this.name + '正在跑步'; }}Fun.prototype = { contructor: Fun, say: function () { return this.name + '正在说话'; }}var f = new Fun();f.run();//Damonare正在跑步f.say();//Damonare正在说话
如上,如果函数作为构造函数用,那么其中的this就代表它即将new出来的对象。为啥呢?new做了啥呢?
伪代码如下:
function Fun() { //new做的事情 var obj = {}; obj.__proto__ = Fun.prototype;//Base为构造函数 obj.name = 'Damonare'; ...//一系列赋值以及更多的事 return obj}
也就是说new做了下面这些事:
(1)创建一个临时对象
(2)给临时对象绑定原型
(3)给临时对象对应属性赋值
(4)将临时对象return
也就是说new其实就是个语法糖,this之所以指向临时对象还是没逃脱上面说的几种情况。
当然如果直接调用Fun(),如下:
function Fun() { this.name = 'Damonre'; this.age = 21; this.sex = 'man'; this.run = function () { return this.name + '正在跑步'; }}Fun();console.log(window)
其实就是直接调用一个函数,this在非严格模式下指向window,你可以在window对象找到所有的变量。
另外还有一点,prototype对象的方法的this指向实例对象,因为实例对象的proto已经指向了原型函数的prototype。这就涉及原型链的知识了,即方法会沿着对象的原型链进行查找。
四.箭头函数
刚刚提到了箭头函数是一个不可以用call和apply改变this的典型。
我们看下面这个:
var a = 1;var obj = { a: 2};var fun = () => console.log(this.a);fun();//1fun.call(obj)//1
以上,两次调用都是1。
那么箭头函数的this是怎么确定的呢?箭头函数会捕获其所在上下文的 this 值,作为自己的 this 值,也就是说箭头函数的this在词法层面就完成了绑定。apply,call方法只是传入参数,却改不了this。
var a = 1;var obj = { a: 2};function fun() { var a = 3; let f = () => console.log(this.a); f();};fun();//1fun.call(obj);//2
如上,fun直接调用,fun的上下文中的this值为window,注意,这个地方有点绕。fun的上下文就是此箭头函数所在的上下文,因此此时f的this为fun的this也就是window。当fun.call(obj)再次调用的时候,新的上下文创建,fun此时的this为obj,也就是箭头函数的this值。
再来一个这里写代码片
:
function Fun() { this.name = 'Damonare';}Fun.prototype.say = () => { console.log(this);}var f = new Fun();f.say();//window
有的同学看到这个会很懵逼,感觉上this应该指向f这个实例对象啊。不是的,此时的箭头函数所在的上下文是proto所在的上下文也就是Object函数的上下文,而Object的this值就是全局对象。
那么再来一个:
function Fun() { this.name = 'Damonare'; this.say = () => { console.log(this); }}var f = new Fun();f.say();//Fun的实例对象
如上,this.say所在的上下文,此时箭头函数所在的上下文就变成了Fun的上下文环境,而因为上面说过当函数作为构造函数调用的时候(也就是new的作用)上下文环境的this指向实例对象。
https://juejin.im/post/59748cbb6fb9a06bb21ae36d?utm_source=weixinqun&utm_medium=fethisinJS
- jquery&js $(this) & this
- js this
- JS this
- JS this
- js this
- js this
- js this
- js this
- JS this
- [js] this
- js--this
- js--this
- js this
- JS- this
- js--this
- js:this
- js this
- js this和$(this)区别
- 今日头条 --新闻阅读器 (二)
- 多继承与菱形继承
- jeesite框架,免登陆直接访问页面设置。
- 句法分析算法PCFG学习
- Maven入门指南④:仓库
- js this
- 提取多层嵌套JSON类型数据
- 浏览器的标准模式和怪异模式
- 负载均衡原理及实现方式
- iOS抓包工具Charles的使用
- jq控制select控件
- 【Java习题】io流习题(自动选流)简单解法
- linux中查看mysql版本的方法
- uboot概念的整理