前言

  通过本文,你大概能了解this基础指向的问题,抛开例子去说this太虚幻,这里还是结合几篇博文做个整理,算是个人的记录了。

先说概念,this指向与申明无关,永远指向距离自己最近的最终调用者。我们从几种调用情况去理解,下面看看例子理解下:

1.函数的直接调用

function a(){
var age = '';
console.log(this.age);//undefined
console.log(this);//window }
a();

如上,我们申明一个函数,然后直接调用,a()前面没任何调用它的对象,这时候我们一般理解为被全局window对象调用,那我们就得去window去找age属性,很明显window没有,这里输出undefined。

我们改改代码,用window去调用函数a,同时定义a的age属性,如下:

window.age = "";
function a(){
var age = '';
console.log(this.age);//
console.log(this);//window
}
window.a();

那我们可以这样理解,针对函数调用,我们在一个函数内申明this,我们去看它最终是被谁调用,如果最终的调用前啥都没有,this就会指向window,这里只是针对js非严格模式。

function a(){
var age = '';
console.log(this.age);//undefined
console.log(this);//window
}
function b(){
a();
}
b();

你以为我说到这,函数调用的this问题就说完了?不存在的,死记硬背难啊,情况多变,为什么函数直接调用,前面啥都没有就指向window,为什么?

  我在知乎看到一篇从函数调用原理讲this的文章,这里就引入下,这是知乎原文 this 的值到底是什么?一次说清楚

  函数一般常见三种调用方式,其实对于我是两种
 
  1.func(a,b)---普通函数调用
 
  2.obj.child.method(context,a,b)---调用对象内的某个方法,这个方法相当于对象的子属性
 
  3.func.call(context,a,b)---这个我确实在调用中没怎么用过。
 
  对于前两种,普通调用,对象属性的函数调用我们都常见,而第三种其实才是我们原本函数该有的调用,那我们这个this的讲解就偏偏与第三种有关系了。我们将前两者改写为第三种调用。
func(a,b) ==>func.call(undefined,a,b)
obj.child.method ==> obj.child.method.call(obj.child,a,b)
//因为不确定obj里面的method是属于obj的属性还是boj child的属性,再加个
obj.method ==> obj.method.call(obj,a,b)

那我们就可以将所有的函数调用统一为  func.call(context,a,b)这一种,如果不是这一种,按照上面去改写,其中context就是我们一直苦苦寻找的this.

OK,上面是函数的普通调用,咱们来改写上面的例子。

function a(){
var age = '';
console.log(this.age);//undefined
console.log(this);//window }
a();//等价于a.call(undefined);

那按照我们上面说的,this应该是undefined啊,为毛是Window,这里又插入一个小规则

如果你传的 context 就 null 或者 undefined,那么 window 对象就是默认的 context(严格模式下默认 context 是 undefined)

那这里我们就明白为啥普通函数直接调用,this指向window了。

  2.函数作为对象属性方法被调用

  怎么去解释,我们还是用上面函数调用的改写去理解,先看一个例子。

var a = {
age:"",
fn:function(){
console.log(this.age); //
}
}
a.fn();//等价于 a.fn.call(a)
//参照obj.method ==> obj.method.call(obj,a,b)来看

method fn是对象a的一个属性,照着上面的对等公式,最终this指向就是对象a自己,也验证了上面我们说的,this指向它最终的的调用者。

再来看一个例子:

var a = {
age:,
func:{
age:,
fn:function(){
console.log(this.age); //
}
}
}
a.func.fn();//等价于 a.method.fn.call(a.method)
//参照obj.child.method ==> obj.child.method.call(obj.child,a,b)来看

func是对象a的一个child属性,而方法fn包含在func内,所以参照这个公司,this指向了a.func,而a.func提供了age属性,这里就输出12了,问题不大吧?

那我们现在来融合函数调用与对象调用来看个例子:

var a = {
age:,
func:{
age:,
fn:function(){
console.log(this.age); //undefined
console.log(this); //window
}
}
}
var j = a.func.fn;
j();//等价于 window.j()或者j.call(undefined)

跟我读,this指向最终,且离自己最近的调用者,最终调用的是方法j(),按照改写说得通,按照我们说的方法前面啥都没有就是window也说的通,就是这个意思了。

 3.构造函数的调用

  我们先来看个例子,当我们输出a.user,this指向了谁?

function Fn(){
this.age = ;
}
var a = new Fn();
console.log(a.age);//

先明白this指向谁,我们要弄懂什么是构造函数,new干嘛了?var a =new Fn()干嘛了?

构造函数就是初始化一个实例对象,当我们new Fn()其实就是将Fn()复制了一份,并作为对象返回,赋值给了变量a。

我们可以console a,得到的就是Fn()函数的实例,而且继承了Fn里面的age属性,所以此时this指向a,a里面有age属性。

我们来白话一遍,这样说,当我们用构造函数方法,this指向我们new出来返回的对象,就是复制Fn得到了一个Fn副本,this指向了Fn副本,而这个Fn副本被赋予给了变量a,于是this指向了a,这个Fn副本继承了原函数的属性,所以这里顺利的输出了25.(并不是复制了整个函数,这句话有问题,我暂时不理解)

 构造函数与return

  我在上面说,构造函数this会指向new之后的实例(复制出来的副本),但如果在函数里有return,this指向可能会发生变化。

function Fn(){
this.age = ;
return {age:};
}
var a = new Fn();
console.log(a); //{age:18}
console.log(a.age);//

很明显,return的对象赋值给了变量a,这里输出了18.再来看看这段代码:

function Fn()
{
this.age = '';
return function(){};
}
var a = new Fn();
console.log(a.age); //undefined

再来一段代码:

function Fn()
{
this.age = ;
return ;
}
var a = new Fn();
console.log(a.age); //

我们可以做个大致判断,当在构造函数中return 一个对象时,this会指向这个对象,如上面的第一 ,第二段代码,但如果return的不是一个对象,那就不会改变this指向,还是指向new 出来的实例。

------取自JS权威指南8.2.3节

大概整理到这,后期再回来填坑。

参考资料

彻底理解js中this的指向,不必硬背。

this 的值到底是什么?一次说清楚

this详解

白话js this指向问题的更多相关文章

  1. 彻底搞懂js this指向问题

    在这里必须要提一句的是,this指向是学习js必须要掌握的(必须),再开始之前先看底部的总结,然后回上面看例子便一目了然. 例子1: function a(){ var user = "Ta ...

  2. JS this指向

    正常模式 在正常模式下独立函数的的 this 指向 undefined 或 window. <script type="text/javascript"> functi ...

  3. JS this指向问题

    <button onclick=(function(){alert(this)})()>I'm button</button>//this指代window <button ...

  4. js this指向理解

    1.如果调用this的函数上级有多个对象,this只会指向上一级对象 下面实例fn函数调用this时,this指向b对象,如果b里面有a属性就输出值: 如果没有就是undefined 在来看下下面的实 ...

  5. JS—-this指向

    箭头函数中this对象就是定义时所在的作用域,也就是说箭头函数本身没有this,内部的this就是外层代码块作用域中的this. 1.独立函数 var a = 0var test = ()=> ...

  6. JS this指向总结

    使用 JavaScript 开发的时候,很多开发者多多少少会被 this 的指向搞蒙圈,但是实际上,关于 this 的指向,记住最核心的一句话:哪个对象调用函数,函数里面的this指向哪个对象. 下面 ...

  7. js this 指向

    JavaScript 作为一种脚本语言身份的存在,因此被很多人认为是简单易学的.然而情况恰恰相反,JavaScript 支持函数式编程.闭包.基于原型的继承等高级功能.由于其运行期绑定的特性,Java ...

  8. js this指向汇总

    this指向 普通函数  window 定时器函数         window 事件函数 事件源 箭头函数 父function中的this,没有就是window 对象函数 对象本身 构造函数 实例化 ...

  9. 可能是史上最强大的js图表库——ECharts带你入门

    PS:之前的那篇博客Highcharts——让你的网页上图表画的飞起 ,评论中,花儿笑弯了腰 和 StanZhai 两位仁兄让我试试 ECharts ,去主页看到<Why ECharts ?&g ...

随机推荐

  1. hbase首次导入大批次的数据成功!

    本次主要是采用hbase自带的importtsv工具来导入.首先要把数据文件上传到hdfs上,然后导入hbase表格.该导入方式只支持.tsv数据文件的导入. 导入流程: 1.下载数据.我们在本文中将 ...

  2. VIM 实现tab标签页及分屏,切换命令

    1,在一个窗口中,VIM 的小tab标签页命令:   :tabnew [++opt选项] [+cmd] 文件            建立对指定文件新的tab :tabc       关闭当前的tab ...

  3. Devexpress中Gridcontrol查找分组

    private void button1_Click(object sender, EventArgs e) { DataTable dt = new DataTable(); dt.Columns. ...

  4. WPF ListBox的进阶使用(二)

    项目中经常使用需要根据搜索条件查询数据,然后用卡片来展示数据.用卡片展示数据时,界面的宽度发生变化,希望显示的卡片数量也跟随变化.WrapPanel虽然也可以实现这个功能,但是将多余的部分都留在行尾, ...

  5. 关于ASP.NET MVC4在IIS6中不认识安卓移动设备的解决办法

    在IIS7中发现安卓的手机浏览器是可以跳转滴. 项目中是采用***.mobile.cshtml来显示移动视图的. 部署到IIS6.0中发现并没有转到*.mobile.cshtml移动视图. 进过漫长的 ...

  6. Lerning Entity Framework 6 ------ Inserting, Querying, Updating, and Deleting Data

    Creating Entities First of all, Let's create some entities to have a test. Create a project Add foll ...

  7. 【CF600E】 Lomsat gelral

    CF600E Lomsat gelral Solution 考虑一下子树的问题,我们可以把一棵树的dfn序搞出来,那么子树就是序列上的一段连续的区间. 然后就可以莫队飞速求解了. 但是这题还有\(\T ...

  8. springboot2 生产部署注意事项【持续更新】

    注意事项1. 去除不需要的 jar 开发工具 jar :springs-boot-devtools2. 监控一定要做好权限制或者去除 控制 jar :spring-boot-starter-actua ...

  9. Python 生成器, 迭代器, 可迭代对象的区别

    1.可迭代对象 在python中, 一切皆对象, 但凡是可以用for循环进行遍历取值的对象都可以称之为可迭代对象, 可迭代对象在程序的一个执行周期中,可以无限轮次的进行循环遍历 2.迭代器 a.一个可 ...

  10. dell 远程管理卡的使用racadm

    尊重作者的劳动,转载请注明作者及原文地址 http://www.cnblogs.com/txwsqk/p/6522854.html 可以直接在浏览器输入管理卡的地址-用户名-密码页面操作 也可以通过命 ...