我也来说说this,谁说this总指向函数的调用者的
先说句题外话,如果你觉得我讲得明白的话给个反馈,点个赞,留个言啥的。学js,如果没弄明白this指向的问题,基本可以说js还没入门。关于this指向的问题,上网搜资料能搜一大把,基本上都是说this总是指向某个对象的,指向函数的调用者的。说对也对,但不全面,如果某个函数没有调用者时,this是指向window的。先来看看是怎么总结出来,“this总是指向函数的调用者的”- console.log(this)//window
- var fun = function(){
- console.log(this);
- };
- fun();//打印window
- // 等价于如下的调用方式
- this.fun();
- window.fun();
- // 匿名函数 可以理解成window创建某个变量保存这个匿名函数,然后删除了这个变量
- (function(){
- console.log(this);
- })();// 打印window
复制代码 这里window调用函数,函数里的this指向window。对象也是一样- var fun = function(){
- console.log(this);
- };
- var o = {
- fn : fun
- }
- o.fn();//打印对象o
- // 如下的方式也没问题
- var a = {
- name : "xiao2",
- sayName : function(){
- alert(this.name);
- }
- };
- a.sayName();//弹出xiao2
复制代码 数组、函数、自定义对象、以及dom对象都是对象,this是指向这个对象的。其他对象的例子不一一举了,这里再举一下dom对象的例子- <section>
- <button id="btn" name="myBtn" style="width:100px;height:30px;">点击我</button>
- </section>
- <script>
- var btn = document.getElementById('btn');
- // 点击按钮时弹出myBtn
- btn.onclick = function(){
- alert(this.name);
- }
- </script>
复制代码 我们点击按钮,触发点击事件,这个onclick函数是btn调用,this指向btn没问题。再看一下构造函数中的this- var Person = function(name,age){
- this.name = name;
- this.age = age;
- this.sayName = function(){
- alert(this.name);
- }
- };
- Person.prototype.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.不把某个函数名,直接赋值某个变量,而是外面加一层函数,然后再调用,换句话说,给你机会来让这个函数执行时指定调用者或者不设置调用者,直接上代码- <section>
- <button id="btn" name="myBtn" style="width:100px;height:30px;">点击我</button>
- </section>
- <script>
- var name="老姚";
- var btn = document.getElementById('btn');
- var f = function(){
- alert(this.name);
- };
- btn.onclick = f;
- </script>
复制代码 上述代码,点击按钮时弹出的是btn对象的name:mybtn。如果想要弹出window中的name,可以改成如下代码- <section>
- <button id="btn" name="myBtn" style="width:100px;height:30px;">点击我</button>
- </section>
- <script>
- var name="老姚";
- var btn = document.getElementById('btn');
- var f = function(){
- alert(this.name);
- };
- btn.onclick = function(){
- f();
- };
- </script>
复制代码 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的$.proxy().这里写个函数- 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);
复制代码
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请
点击举报。