博客列表 >简析js中的this的指向

简析js中的this的指向

Coco
Coco原创
2021年12月13日 15:19:09359浏览

  回想当初在切图网做前端项目,用到js,经常用到this;那我们就谈谈js中this,如果说你没弄清this指向的问题,那基本可以说js没入门。

  this指向的问题的文章,上网搜资料能搜一大把,基本上都是说this总是指向某个对象的,指向函数的调用者的。

  如果某个函数没有调用者时,this是指向window的。

  先来看看是怎么总结出来,“this总是指向函数的调用者的”

  console.log(this)//window

  var fun=function(){

  console.log(this);

  };

  fun();//打印window

  // 等价于如下的调用方式

  this();

  window();

  // 匿名函数 可以理解成window创建某个变量保存这个匿名函数,然后删除了这个变量

  (function(){

  console.log(this);

  })();// 打印window

  这里window调用函数,函数里的this指向window。

  对象也是一样

  数组、函数、自定义对象、以及dom对象都是对象,this是指向这个对象的。其他对象的例子不一一

  举了,这里再举一下dom对象的例子

  

  

  

  

  我们点击按钮,触发点击事件,这个onclick函数是btn调用,this指向btn没问题。

  再看一下构造函数中的this

  var Person=function(name,age){

  this.name=name;

  this.age=age;

  this.sayName=function(){

  alert(this.name);

  }

  };

  Persontotype.sayAge=function(){

  alert(this.age);

  };

  var p=new Person("切图网",18);

  p.sayName();//弹出 切图网

  p.sayAge();//弹出 18

  new一个函数时,函数也会执行的。可以看做p调用了Person这个构造函数,里面的this.name、this.age 、this.sayName中的this都是指向p的;

  p.sayName()、p.sayAge()是p调用函数,这两个里面的this当然指向对象p了。

  从上面的代码中,基本可以总结了,this总是函数调用者的。那么再看看如果函数没用调用者呢?

  var o={

  fn : function(){

  console.log(this); // 标记1

  var a=function(){

  console.log(this);// 标记2

  };

  a();

  }

  };

  o.fn();//标记1 打印对象o,标记2 打印window

  你说上述代码中执行语句a(),a调用者是谁?是对象o吗,是window吗,都不是,如不信,你改成o.a()或者window.a(),浏览器肯定会报错的。

  a是没有调用者,你只能说在fn的作用域中,a被调用了。而此时函数没有调用者时,里面的this指向window的。

  this的指向的问题我是说明白了,再总结一下:如果函数有调用者时,this指向调用者,如果没有调用者,this指向window的。上述代码中,都没有涉及闭包问题。

  这里举个例子

  var b=function(){

  console.log(this); // 标记1

  return function(){

  console.log(this);// 标记2

  }

  }

  var c=b();//标记1 打印window

  c();// 标记2 打印window c是被window调用的,打印window没问题

  var a={

  fn : c

  }

  a.fn();// 标记2 打印对象a,没问题

  //如下方式呢

  var e={

  fn : function(){

  c();

  }

  }

  e.fn();// 标记2 打印window 因为c()是没有调用者的

  可以看出,不管是不是闭包,还是那句话,能找到调用者就指向调用者,找不到就指向window。

  《js高级程序设计》里面是这么说的,匿名函数的执行环境具有全局性的。我是这么看的,找不到调用者时,执行函数就具有全局性。跟你这个函数是不是有名匿名没有任何关系。

  第二部分

  如何保证this,是我们想要的this呢

  有几个方法,这里大致说下

  1.不把某个函数名,直接赋值某个变量,而是外面加一层函数,然后再调用,换句话说,给你机会来让这个函数执行时指定调用者或者不设置调用者,直接上代码

  

  

  

  

  上述代码,点击按钮时弹出的是btn对象的name:mybtn。如果想要弹出游戏账号拍卖window中的name,可以改成如下代码

  

  

  

  

  2.设置变量缓存this,如

  var name="yyy";

  var Person=function(name){

  this.name=name;

  (function(){alert(this.name)})();

  }

  new Person("xxx");

  上代码运行会弹出window的name:yyy,如果想弹出对象的name:xxx,可以改成

  var name="yyy";

  var Person=function(name){

  this.name=name;

  var self=this;

  (function(){alert(self.name)})();

  }

  new Person("xxx");

  3.应用call、apply方法来指定this

  var name="yyy";

  var o={name: "xxx"};

  var fun=function(x,y){

  alert(this.name)

  return x+y;

  }

  fun(3,4);

  // 等于于如下的调用

  fun.call(window,3,4);

  fun.call(this,3,4);

  fun.apply(window,[3,4]);

  fun.apply(this,[3,4]);

  上述代码运行弹出window的name:yyy,如果要弹出o的name,可以改成

  var name="yyy";

  var o={name: "xxx"};

  var fun=function(x,y){

  alert(this.name)

  return x+y;

  }

  fun.call(o,3,4);

  fun.apply(o,[3,4]);

  4.应用框架函数,一般的框架都有给函数绑定上下文的函数(基本也都是应用apply和call),比如jquery的$xy().这里写个函数

  function proxy(fn,context){

  return function(){

  fn.apply(context,arguments);

  }

  }

  var o={name: "xxx"};

  var fun=function(x,y){

  alert(this.name)

  return x+y;

  }

  var fun2=proxy(fun,o);

  fun2(3,4);

  文/丁向明

  做一个有博客的web前端自媒体人,专注web前端开发,关注用户体验,加我qq/微信交流:6135833

  dingxiangming

声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议