this的指向

文章来源:http://cherryblog.site/call-apply-bind-this.html#more

this的指向

this的用法是经典的面试问题,不了解本质原理,一不小心就会入坑,所以在接下来我们深入其本质,探寻this的用法,重要的是记住this永远指向最后调用它的那个对象。
下面看一些简单的例子:
ex1:

        var name = "windowsName";
        function a() {
            var name = "Cherry";
            console.log(this.name);// windowsName
            console.log("inner:" + this);// inner: Window
        }
        a();
        console.log("outer:" + this)  

从上面的例子中我们能看到最后调用函数a的地方是a(),前面没有调用的对象,所以就是全局对象window调用的a(),相当于window.a(),所以在执行函数a的过程中,this的指向是window。
ex2:

        var name = "windowsName";
        var a = {
            name: "Cherry",
            fn : function () {
                console.log(this.name); // Cherry
            }
        }
        a.fn();

fn()被a调用。所以在执行fn的过程中this指向a,this.name就等于Cherry。
ex3:

var name = "windowsName";
        var a = {
            // name: "Cherry",
            fn : function () {
                console.log(this.name); // undefined
            }
        }
        window.a.fn();

fn()被对象a调用,但是对象a并没有定义name,所以this.name等于undefined,即使window中有name属性,也不会继续向上一个对象寻找,而是直接输出。
ex4:

        var name = "windowsName";
        var a = {
            name : null,
            // name: "Cherry",
            fn : function () {
                console.log(this.name);// windowsName
            }
        }
        var f = a.fn;
        f();

对象a的fn方法直接赋给了f,但是没有被调用,而是由window调用了f(),所以在执行fn()的过程中,this指向的是window。

从上面4个例子可以看出,this的指向并不是在创建的时候就可以确定的,永远是this永远指向最后调用它的那个对象。

怎么改变this的指向

有以下几种方法:
1、使用箭头函数
2、在函数内部使用:that=this
3、使用apply、call、bind
4、new实例化一个对象

ex5:

        var name = "windowsName";
        var a = {
            name : "Cherry",
            func1: function () {
                console.log(this.name)     
            },
            func2: function () {
                setTimeout(  function () {
                    this.func1()
                },100);
            }
        };
        a.func2()     // this.func1 is not a function

该例子会报错,因为最后调用setTimeout的对象是window,但是在window中没有func1函数。

对上面的例子进行改造:

箭头函数
箭头函数的this始终指向函数定义时的this,而非执行时。箭头函数中没有this绑定,必须通过查找作用域链来决定其值。如果箭头函数被非箭头函数包含,则this绑定的是最近一层非箭头函数的this,否则this为undefined。
ex6:

var name = "windowsName";
        var a = {
            name : "Cherry",
            func1: function () {
                console.log(this.name)     
            },
            func2: function () {
                setTimeout( () => {
                    this.func1()
                },100);
            }
        };
        a.func2()     // Cherry

在函数内部使用that=this

我们最先将调用这个函数的对象报保存在变量that中,然后在函数中使用这个that,这样that就不会改变。

        var name = "windowsName";
        var a = {

            name : "Cherry",
            func1: function () {
                console.log(this.name)     
            },
            func2: function () {
                var _this = this;
                setTimeout( function() {
                    _this.func1()
                },100);
            }
        };
        a.func2()       // Cherry

首先设置that=this,这里的this是调用func2的对象a,为了防止在func2中的setTimeout被window调用,将this赋值给一个变量that,这样在func2中我们使用的that就是指向对象a。

使用apply、call、bind

        var a = {
            name : "Cherry",
            func1: function () {
                console.log(this.name)
            },
            func2: function () {
                setTimeout(  function () {
                    this.func1()
                }.apply(a),100);
            }
        };
        a.func2() 
        var a = {
            name : "Cherry",
            func1: function () {
                console.log(this.name)
            },
            func2: function () {
                setTimeout(  function () {
                    this.func1()
                }.call(a),100);
            }
        };
        a.func2() 
        var a = {
            name : "Cherry",
            func1: function () {
                console.log(this.name)
            },
            func2: function () {
                setTimeout(  function () {
                    this.func1()
                }.bind(a),100);
            }
        };
        a.func2() 

apply、call、bind 区别
在MDN中定义apply如下:
apply()方法调用一个函数,其具有一个指定的this值,以及作为一个数组提供的参数。

语法:

fun.apply(thisArg,[argsArray])

thisArg: 在fun函数运行时指定的this值。需要注意的是,指定的this值不一定是该函数执行时真正的this值,如果这个函数处于非严格模式下,则指定为null或undefined时会自动指向全局对象,同时值为原始值的this会指向该原始值的自动包装对象。

argsArray:一个数组或类数组对象,其中的数组元素将作为单独的参数传给fun函数。如果改参数的值为null或undefined,则表示不需要传入任何参数。

apply和call区别是call方法接受的是若干个参数列表,而apply接受的是一个包含多个参数的数组。

var a ={
    name : "Cherry",
    fn : function (a,b) {
        console.log( a + b)
    }
}
var b = a.fn;
b.apply(a,[1,2]);   
var a ={
    name : "Cherry",
    fn : function (a,b) {
        console.log( a + b)
    }
}
var b = a.fn;
b.apply(a,1,2);   

bind()方法创建一个新的函数,当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前将提供一个给定的参数序列。我们必须手动调用。

var a ={
    name : "Cherry",
    fn : function (a,b) {
        console.log( a + b)
    }
}
var b = a.fn;
b.bind(a,1,2)()  

JS中的函数调用
函数调用的方法一共有四种:
1、作为一个函数调用
2、函数作为方法调用
3、使用构造函数调用函数
4、作为函数方法调用函数

作为一个函数调用

var name = "windowsName";
function a() {
    var name = "Cherry";
    console.log(this.name);       // windowsName
    console.log("inner:" + this); // inner: Window
}
a();
console.log("outer:" + this)      // outer: Window

这样一个最简单的函数,不属于任何一个对象,就是一个函数,在浏览器的非严格模式下默认是属于window的,在严格模式下就是undefined。

函数作为方法调用

var name = "windowsName";
var a = {
    name: "Cherry",
    fn : function () {
        console.log(this.name);      // Cherry
    }
}
a.fn();

使用构造函数调用函数

// 构造函数:
function myFunction(arg1, arg2) {
    this.firstName = arg1;
    this.lastName  = arg2;
}

// This    creates a new object
var a = new myFunction("Li","Cherry");
a.lastName; 

这里就要说另一个经典的面试题:new的实例化过程
伪代码表示:

var a=new myFunction("li","Cherry");
new myFunction(){
var obj={};
obj._proto_=myFunction.prototype;
var result=myFunction.call(obj,"li","Cherry");
return typeof result==='obj'?result:obj;
}

1、创建了一个空对象obj
2、将创建的空对象的隐式原型指向其构造函数的显示原型
3、使用call改变this的指向
4、如果无返回值或者返回一个非对象值,则将obj返回作为新对象;如果返回值是一个新对象的话那么直接返回该对象。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
自动控制节水灌溉技术的高低代表着农业现代化的发展状况,灌溉系统自动化水平较低是制约我国高效农业发展的主要原因。本文就此问题研究了单片机控制的滴灌节水灌溉系统,该系统可对不同土壤的湿度进行监控,并按照作物对土壤湿度的要求进行适时、适量灌水,其核心是单片机和PC机构成的控制部分,主要对土壤湿度与灌水量之间的关系、灌溉控制技术及设备系统的硬件、软件编程各个部分进行了深入的研究。 单片机控制部分采用上下位机的形式。下位机硬件部分选用AT89C51单片机为核心,主要由土壤湿度传感器,信号处理电路,显示电路,输出控制电路,故障报警电路等组成,软件选用汇编语言编程。上位机选用586型以上PC机,通过MAX232芯片实现同下位机的电平转换功能,上下位机之间通过串行通信方式进行数据的双向传输,软件选用VB高级编程语言以建立友好的人机界面。系统主要具有以下功能:可在PC机提供的人机对话界面上设置作物要求的土壤湿度相关参数;单片机可将土壤湿度传感器检测到的土壤湿度模拟量转换成数字量,显示于LED显示器上,同时单片机可采用串行通信方式将此湿度值传输到PC机上;PC机通过其内设程序计算出所需的灌水量和灌水时间,且显示于界面上,并将有关的灌水信息反馈给单片机,若需灌水,则单片机系统启动鸣音报警,发出灌水信号,并经放大驱动设备,开启电磁阀进行倒计时定时灌水,若不需灌水,即PC机上显示的灌水量和灌水时间均为0,系统不进行灌水。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值