函数上下文this

1:直接圆括号执行 this指的是window对象    IIFE也属于圆括号直接执行  this 只想window


例1

var obj = {
    as:100,
    fun: function(){
    alert(this.as)
}
}
var b = obj.fun
b()
//输出undefined

例2

var a = 300;
var obj = {
    a : 100,
    b:(function(){
    alert(this.a)
    })()
}
//弹出300

例3

var xiaohong = {
    name : "小红",
    age : 25,
    hello : (function(){
        return this.age > 18? "女士" : "女生"
    })()
}
alert ("大家好,我叫" + xiaohong.name + ",我是一个" + xiaohong.hello)


结果为女生

IIFE 里的this指的是window 所以this.age 是undefined    undefined > 18 是false  所以返回的是 女生

例4

var obj = {
    a: 100,
    fun: function() {
        var a = 200;
        alert(this.a)
    }
}
var a = 300;
var f = obj.fun
f()
//结果300

解析:条用的时候是圆括号直接调用的  所以这里this指向了window   而全局变量都是window对象的属性  →最后弹出300(其它的a都是障眼法)

2 从对象中调用或者数组枚举执行的函数  上下文this指的是这个对象或者数组

例1

function fun1(a, b, c) {
    arguments[0]()
}

function fun2(a, b, c, d, e) {
    alert(this.length)
}
fun1(fun2, 9, 2, 4, 2, 34, 234)、
//7

解析:this指的是谁要看谁在调用。函数fun1调用的时候 函数的执行是 arguments[0]的执行 ,因为arguments是fun1的实参列表,所以第0项就是fun2函数,所以符合规则;fun2函数中的this指的就是fun1函数的arguments类数组对象,所以length就是7

例2

function fun1(a, b, c) {
    arguments[0](1, 2, 3, 4, 5, 6)
}

function fun2(a, b, c, d, e) {
    alert(this.length) // 7
    alert(arguments.length) // 6
    alert(arguments.callee.length) // 5
    alert(this.callee.length) // 3
}
fun1(fun2, 9, 2, 4, 2, 34, 234)

解析:

与例1类似 fun2中的this指的是fun1函数,所以此时this.length指的就是fun1的arguments类数组对象(因为是类数组枚举执行的符合规则);

arguments本身是fun2函数自己的实参列表,所以长度是6(调用的时候传了1~6的参数);

我们知道arguments.callee是fun2函数自己,所以length就是形参列表为5;

this.callee.length指的就是fun1的形参列表为3

例3

var m = 2;
var obj = {
    fun1: function() {
        return this.fun2()
    },
    fun2: fun2,
    m: 4
}

function fun2() {
    return this.m;
}
alert(obj.fun1()) 
// 4

解析  打点执行  this指向 obj    而obj.m  就是4

例4

var num = 1; // 5 , 25 , 125
var obj = {
    num: 2, // 10 , 50
    fun: (function() {
        var num = 3;
        this.num += 4;
        return function() {
            this.num *= 5;
            num *= 6; // 18 , 108 , 648 , 
            alert(num)
        }
    })()
}
obj.fun() 			// 18
obj.fun() 			// 108
alert(num) 		// 5
alert(obj.num) 	// 50
var f1 = obj.fun
f1() 				// 648
alert(num) 		// 25
alert(obj.num) 	// 50
var f2 = obj.fun
f2() 				// 3888
alert(num) 		// 125

解析: obj.fun() →IIFE只执行一次 且this指向window  所以全局的num = 1+4 是5   接着obj.fun() this指向obj 此时 obj的num 先变成2*5 是10  。num*=6   此时num是3 所以 *6就是18  结果为18

            obj.fun()→ IIFE不再执行  所以全局的num 是5。接着obj.fun() this指向obj 此时 obj的num 先变成10*5 是50 。num*=6   此时num是18 所以 *6就是108 结果为108

            alert(num)→ 全局的num 就是5

            alert(obj.num)→ obj的num 就是50

           var f1 = obj.fun

           f1()→ 圆括号直接执行 this指向window  所以 this.num *= 5指的是全局的num*5 结果25 num*=6   此时num是108 所以 *6就是648结果为648

           alert(num)  →      全局的num 就是25

           alert(obj.num)obj的num→ 是50

           var f2 = obj.fun

           f2()→圆括号直接执行 this指向window  所以 this.num *= 5指的是全局的num*5 结果125 num*=6   此时num是648 所以 *6就是3888结果为3888

          alert(num)→全局的num 就是125

例5

var length = 1;
var obj = {
    length: 10,
    b: [{
        length: 20,
        fun: function() {
            alert(this.length)
        }
    }]
}
var arr = [obj, obj.b, obj.b[0], obj.b[0].fun]
arr[0].b[0].fun() // 20
arr[1][0].fun() // 20
arr[2].fun() // 20
arr[3]() // 4

解析  前边三个最后返回的都是 对象

{

        length: 20,

        fun: function() {

            alert(this.length)

        }

    }在执行所以this指向这个对象   结果都是20 

arr[3]()  这个是数组通过枚举法在执行   所以this指的是 这个数组   它的length就是4

3 定时器直接调用,上下文是window对象

例1

var obj = {
    a: 300,
    fun: function() {
        console.log(this.a++)
    }
}
var a = 100;
setInterval(obj.fun, 1000)
//100 100 100.。。。。。。。。。。。
var obj = {
    a: 300,
    fun: function() {
        console.log(this.a++)
    }
}
var a = 100;
setInterval(function() {
    obj.fun()
}, 1000)
// 301 302 303.............

4 DOM事件中的this,指的是触发事件的这个DOM元素

5 call()和apply()可以设置函数的上下文

例1:

function fun1() {
    fun2.apply(obj, arguments)
}

function fun2(a, b, c) {

    console.log(obj)
    console.log(a)
    console.log(b)
    console.log(c)
}
var obj = {
    name: '小明',
    sex: '男'
}
fun1("香蕉", '葡萄', '梨子')

解析:apply有一个功能,可以将第二个参数(类数组参数)进行解构,变成一个罗列的参数。比如传进arguments是一个类数组对象,但是在fun2函数接受的a,b,c形参中给进行了解构,也就是分别变成了香蕉、葡萄、梨子

例2 利用apply求数组最值

Math.max.apply(null, [789, 2342, 123, 2134, 2345, 22])

综合实战题目

第一题

var a = 1;

function fn() {
    this.a++;
    a += 10;
    var a = 8;
}
fn()
alert(a)//2

解析:因为fn执行的时候内部的this指的是window也就是全局的a=1,所以this.a++ 等于2;函数内部的a += 10本质上是undefined+= 10 结果为NaN,因为后面有个var a = 8;因为变量声明提升的原因造成的。alert的是全局的a

第二题

var length = 5;
var arr = [fn1, fn2];

function fn1() {
    return this.length;
}

function fn2() {
    return this[0]
}
var a = arr[0]()
var b = arr[1]()()
console.log(a) // 2
console.log(b) // 5

解析:a =arr[0]()是数组的枚举法执行this指的是这个数组  所以数组的length就是2。 b = arr[1]()()   arr[1]()是数组的枚举法执行this就是这个数组,这部分执行之后return出一个函数,这个函数圆括号执行this就是window   所以结果就是5

第三题

var number = 2; // 4,16
var obj = {
    number: 3, // 12,24
    fn1: (function() {
        this.number *= 2;
        number = number * 3; // NaN
        var number = 2; // 10,50
        return function() {
            this.number *= 4;
            number *= 5;
            alert(number)
        }
    })(),
    fn2: function() {
        this.number *= 2;
    }
}
var fn1 = obj.fn1;
alert(number) 				// 4
fn1() 						// 10
obj.fn1() 					// 50
obj.fn2()
alert(window.number) 		// 16
alert(obj.number) 			// 24

解析:obj 里面的fn1是IIFE 声明之后立即执行一次 此时this指的是window  所以window的number 就变成  number*=2即 4。

          fn1()圆括号打点执行 this指的是window fn1此时是obj.fn1 return出来的函数   this.number *=4 这时候全局的number就是4*4 = 16     number*=5 指的就是上边声明的number2*5  就是10alert结果就是10

          obj.fn1() 对象打点执行this就是这个对象  this.number *= 4;就是obj的number*4 即 3*4 =12。 number*=5 指的就是上边声明的number10*5  就是50alert结果就是50

          obj.fn2() 对象打点执行this就是这个对象   this.number *= 2 就是obj的number*2 即 12*2=24

         最后alert(window.number)即为16

                 alert(obj.number)即为24

 

第四题

var length = 5;

function getLength() {
    return this.length 
}

function foo() {
    this.length = 1;
    return (function() {
        var length = 2;
        return {
            length: function(a, b, c) {
                return this.arr.length;
             },
            arr: [1, 2, 3, 4],
            info: function() {
                return getLength.call(this.length)
            }
        }
    })()
}
var result = foo().info()
console.log(result) // 3

解析:因为result是foo执行的之后的函数执行,foo执行返回的是一个对象,这个对象打点调用info,info函数中执行了getLength函数,并且将上下文一同绑定了,绑定的是对象的length属性,该属性值是一个函数,所以getLenth函数在执行时候的this就是这个对象的length函数,this.length也就是该函数的形参length结果为3

 

 

 

 

 

 

 

 

 

 

 

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 游动-白 设计师:上身试试 返回首页