当前位置: 首页 > article >正文

surfacecreated啥时被调用_JavaScript当中的this究竟是个啥?

77d1db0a3b35fd89badc2baaefd5bf97.png

前言

原文:JavaScript当中的this究竟是个啥?

对于JS的初学者而言,JS当中的this指向很难让人摸准其脉络,经常会给你一种模糊美、朦胧美的感觉!因为this并不是固定不变的,它会根据自身所执行的环境的不同而不同。而且在开发的过程中,经常因为对this的不了解出现这样或那样的错误!所以搞定this的指向是非常非常有必要的!

this指向

与其它语言当中的this不同的是,JS当中的this总是指向一个对象。而具体是指向哪一个对象,则要看其运行时是基于哪一个函数的执行环境所动态绑定的。

注意:this的指向并不是函数被声明时的环境。

具体到实际开发中,this的指向大致可以分为以下几种:

1、作为普通函数调用

当你的函数不是作为对象的属性来调用时,即是我们经常说的普通函数调用。此时的this为全局对象,而JS当中的全局对象指的是window。
作为普通对象调用:

//定义一个全局变量age
var age=18;
//声明一个全局函数getAge
function getAge(){return this.age;
}
//因为是全局环境内调用的getAget函数所以指向的对象为window
console.log(getAge());//18
//你也可以这样写
console.log(window.getAge());//18

以上代码中,getAge方法在全局window下调用,所以getAge方法内的this指向的是window。为了更好的验证这一点,咱们再来对以上代码修改如下:

//声明一个全局函数getAge
function getAge(){//由于该函数在全局环境(window)下调用,所以this为windowthis.age=81;//为this指向的window对象添加属性age
}
getAge();//全局调用函数getAge()
console.log(age);//81
//也可以这样输出
console.log(window.age);//81

以上代码中声明了一个全局函数getAge。由于该函数在全局环境(window)下调用,所以this为window。然后通过this.age为window对象增加一个age属性。所以在调用完该函数后进行console.log(window.age)输出的结果为81。

2、函数作为对象的属性来调用:

如果函数作为对象的属性来调用,函数内的this为调用函数的对象。

var obj={//obj属性ageage:12,//obj方法getAgegetAge:function(){return this.age;}
}
//全局属性age
var age=13;
//全局方法getAge
function getAge(){return this.age;
}
//在obj对象下调用getAge(),this代表的是obj
console.log(obj.getAge());//12

在全局环境下,this代表的是window。所以调取的方法为全局方法getAge。又因为getAge是在window下调用的,所以内部this指向的是window对象。最终输出结果为13

var obj={//obj属性ageage:12,//obj方法getAgegetAge:function(){return this.age;}
}
//全局属性age
var age=13;
//全局方法getAge
function getAge(){return this.age;
}
//在全局环境下,this代表window,所以下面可以理解为window对象下调用全局getAge
console.log(this.getAge());//13

接下来看种丢失掉this的情况,换言之,this的指向发生改变。我们先来看下面的代码

var obj={//obj属性ageage:12,//obj方法getAgegetAge:function(){return this.age;}
}
//全局属性age
var age=13;
//全局方法getAge
function getAge(){return this.age;
}
//在obj对象下调用getAge(),this代表的是obj
console.log(obj.getAge());//12
//将obj下的函数getAge赋值给fn。
var fn=obj.getAge;
//在全局环境(window) 下调用fn,this代表的是window
console.log(fn());//13

当调用obj.getAge时,getAge方法是作为obj对象的属性来调用的。输出结果为12。当将obj.getAge赋值给一个变量fn时,因为fn的调用是在全局环境下调用的,所以this指向的是window,输出结果为13。
将代码汇总如下,认真看看:

var obj={//obj属性ageage:12,//obj方法getAgegetAge:function(){return this.age;}
}
//全局属性age
var age=13;
//全局方法getAge
function getAge(){return this.age;
}
//在obj对象下调用getAge(),this代表的是obj
console.log(obj.getAge());//12
//在全局环境下,this代表window,所以下面可以理解为window对象下调用全局getAge
console.log(this.getAge());//13
//将obj下的函数getAge赋值给fn。
var fn=obj.getAge;
//在全局环境(window) 下调用fn,this代表的是window
console.log(fn());//13

3、DOM对象的事件函数

DOM对象的事件函数内的this指向的是该DOM对象,看以下代码:

<body><div id="myDiv">点我吧!</div>
</body>
<script>//为id为"myDiv"增加点击事件document.getElementById("myDiv").onclick=function(){//this为divconsole.log(this.id);//myDiv}
</script>

在事件函数内添加一个子函数_fn,该子函数内的this指向的是window:

<body><div id="myDiv">点我吧!</div>
</body>
<script>var id="window";document.getElementById("myDiv").onclick=function(){function _fn(){console.log(this.id);//window}_fn();}
</script>

但往往我们需要的是让它指向触发事件的DOM对象,此时有一种解决方法可以作为参考:

<body><div id="myDiv">点我吧!</div>
</body>
<script>var id="window";document.getElementById("myDiv").onclick=function(){var _this=this;//保存对myDiv的引用function _fn(){console.log(_this.id);//myDiv}_fn();}
</script>

4、构造函数

在JS当中并没有类的概念,但是我们可以通过构造函数来创建对象,而且JS也提供了new操作符,使构造函数看起来更像是一个类!
构造函数与普通函数的异同:构造函数与普通函数的个表是一样的,它们的区别在于调取的方式。当用new操作符调用函数时,该函数为构造函数,否则为普通函数。

function Box(){this.age=14;
}
var obj=new Box();
console.log(obj.age);//14

通过new来调用构造函数时的执行流程如下:
* new 构造函数(),隐式执行了new Object();
* 将构造函数的作用域给新对象(即new Object()创建出的对象),函数体内的this就代表这个新对象。
* 执行构造函数的语句。
* 隐式直接返回新对象。
需要注意的是构造函数如果直接返回一个对象,那么执行返回的对象就不是我们所期待的this:

function Box(){this.age=14;return {age:16}
}
var obj=new Box();
console.log(obj.age);//16

5、通过call与apply改变this的指向

通过call与apply可以动态的改变函数内的this

//声明一个全局变量color
var color="red";
//声明一个全局对象obj,为 obj添加一个属性color值为yellow
var obj= {color: "yellow"
}
//添加一个构造函数
function Fn(){this.color="blue";
}
//普通函数
function getColor(){console.log(this.color);
}
getColor();//red
getColor.call(window);//red
getColor.call(this);//red
getColor.call(obj);//yellow
getColor.call(new Fn());//blue

以上代码通过call来改变函数体内this的指向,以上代码用apply也是可以实现相同的功能。只需要将call改变apply即可:

var color="red";
var obj= {color: "yellow"
}
function Fn(){this.color="blue";
}
function getColor(){console.log(this.color);
}
getColor();//red
getColor.apply(window);//red
getColor.apply(this);//red
getColor.apply(obj);//yellow
getColor.apply(new Fn());//blue

call与apply的用法是一样,区别仅在于传入的参数形式不同。

var num=5;
function fn(num1,num2){console.log(num1+num2+this.num);
}
var obj={num:8
}
fn.call(this,1,2);//8
fn.call(obj,1,2);//11
//apply 传递的参数需要用中括号进行包裹
fn.apply(this,[3,4]);//12
fn.apply(obj,[3,4]);//12

6、通过bind指定函数内部的this

var age=81;
var obj={age:18
}
//指定fn函数体内的this指向window
var fn=function(){console.log(this.age);
}.bind(this);
//指定fn2函数体内的this指向obj
var fn2=function(){console.log(this.age);
}.bind(obj);
fn();//81
fn2();//18

e075e702cb870289d726105af4999ddd.gif
http://www.lryc.cn/news/2414458.html

相关文章:

  • 第一节:1. 美国域名中心US Domain Center是什么,为什么选择它作为建站平台
  • 城市筛选检索
  • MySQL修改表(ALTER TABLE语句)
  • ORA-01008: 并非所有变量都已关联
  • 设计超炫的3D窗体旋转特效(windows7中所没有的特性)
  • 分享到QQ、QZone方法,无需登录
  • VMware Workstation 虚拟机 安装CentOS 8
  • CSMA/CA协议 80211
  • 多线程基础之二:mutex和semaphore使用方法
  • 移位寄存器及其应用
  • 赛门铁克端点防护(英語:)是由博通公司开发的安全软件套件,包括杀毒软件、入侵检测系统和防火墙,适用于服务器和台式电脑,在端点安全产品中拥有最大的市场份额。
  • 详细的图文Windows电脑设置自动关机/计划关机
  • WDM驱动模型简介
  • Flex4中文字幕教学视频(翻译自Adobe开发者中心)+ 离线下载播放器
  • 苹果电脑是“监狱”、弃用 Ubuntu,GNU 创始人斯托曼谈自由软件运动现状
  • 海龟绘图小案例(内含源码)
  • 针对没有光驱,NTLDR is missing系统无法启动的解决办法
  • 虚幻引擎3(Unreal Engine 3)概要
  • C 语言(基础笔记)
  • 最新d3dx9_33.dll文件丢失解决
  • 《社交网络》中Facemash算法分析
  • Android 版本区别
  • 网络通信原理——OSI模型、TCP/IP模型、数据通信原理
  • 常见的用户密码在后台数据库中加密存储方式
  • 办公楼综合布线系统详细设计方案
  • 路由器的类型及衡量路由器性能的主要参数指标
  • html引入html include_CSS的引入方式笔记
  • 为什么在Spring应用中不建议使用属性注入(Field Injection)
  • 本地代码与托管代码
  • mysqlbinlog -v与-vv --base64-output 与不加的区别