js中this的指向问题

上周小组讲课讲的有this的指向,所以今天将上次讲课的知识点整理了一遍,再回忆一下。

this指向:在绝大多数情况下,函数的调用方式决定了this的值(运行时绑定),通俗的说,谁调用了我,我就指向谁。

1.首先了解window是浏览器对象

BOM的概述 browser object modal :浏览器对象模型。 浏览器对象:window对象。 Window 对象会在<body><frameset> 每次出现时被自动创建。

我们经常在js中调用一个函数通常是函数名加(),其实本质上是window.函数;例如:

var a=1;
console.log(a);//输出为1
console.log(window.a);//输出为1

2.现在开始说this,如刚开始所说,this的指向可以说是谁指向了我,我就指向谁,跟我们指向的地址去找this。
先来一个例子结合上一条对this进行一下了解

function typeOne(a){
    console.log('1 在html标签内声明函数,该方法this为:')
    console.log(this);
}
typeOne(1);//此时的输出结果为window,typeOne(1),可以写成window.typeOne(1)的形式。所以是window调用的函数,this就指向window。

2.1三种函数调用来讨论this指向
2.1.1:纯粹的函数调用

function  func() {
    console.log( this.a );
}
func();
window.func();//undefined --this指向window
console.log(window.a);

这两个的输出都是undefined,window.func()中的this指向的是window,与func()一样。为什么结果是undefin呢?

这是因为this指向的是window,而window.a就相当于在全局定义了一个a的变量,但是没有进行赋值,所以输出的结果为undefined.

现在我们将a进行赋值

var a=5;
function  func() {
    console.log( this.a );
}
window.func();//undefined --this指向window
console.log(window.a);
console.log(window);

此时的输出结果都为5,这是因为我们在全局定义了一个a变量,并且对a进行了赋值,所以此时window是由a这个属性的,他的属性值就是5,输出的window中有a这个属性,属性值为5
2.1.2:作为对象方法调用

function  func() {
    console.log( this.a );
}
var  obj = {
    a: 42,
    func:func
};
obj.func();
window.obj.func();  // 42 -- this指向obj

这种方式是obj调用的func(),此时obj中有属性a,且a的值为42,所以输出的结果为42

我们在上一段代码的基础上,加上这一段代码

var obj2={
    a: 66,
    obj: obj
}
obj2.obj.func()  //如果有多个对象调用我,那我就指向最后一个,即obj

此时可以理解为是obj2调用obj,obj调用func(),所以还是obj调用func(),所以结果为42
2.1.33.作为构造函数调用 构造函数就是通过这个函数可以生成一个新的对象,这是,this就指这个新对象。

function test() {
    this.x = 1;
    console.log(this.x)
}

var obj = new test();
obj// 1

这种方法obj对象中有x属性所以输出为1

var x=2;
function test() {
    console.log(this.x)
}

var obj = new test();
obj// undefined

这种方法得到结果为undefined,这是因为obj这个对象中有test函数,没有a独享,是obj调用的test()函数,所以为undefined

var x=2;
function test() {
    this.x=1
    console.log(this.x)
}

var obj = new test();
obj// 1

这样子就更好理解了
2.2:通过三种方式对DOM节点添加点击事件
2.2.1.第一种方式:内敛方式
在html标签内声明函数 html代码为

  <button onclick="typeOne()">第一种</button>
    <button onclick="window.typeOne()">第一种</button>

js代码为

function typeOne(){
    console.log('1 在html标签内声明函数,该方法this为:')
    console.log(this);
}

此时指的对像为window对象

这是因为点击按钮的时候,相当于执行了typeOne()函数,此时函数的执行范围是全局对象window,此时还是window调用了这个函数,所以this指向的还是window对象
2.2.2.第二种方式 :动态绑定,在js中为DOM对象绑定onclick事件

  <button id="two">第二种</button>
two.onclick=function(){
    console.log('2 onclick直接绑定,该方法this为:');
    console.log(this);

};

此时的输出结果为 button标签,此时this指向的是DOM对象,这是因为我们对DOM对象中的onclick属性赋值了一个函数,此时是DOm对象调用的这个函数,所以this指向的是DOM对象。这种绑定事件,只能绑定一次,如果多次绑定就会覆盖。

two.onclick=function(){
    console.log('2 onclick直接绑定,该方法this为:');
    console.log(this);


};
two.onclick=function(){
    console.log('2 onclick直接绑定,第二次绑定,该方法this为:');
    console.log(this);
};

此时输出的结果为第二次绑定,this输出还是button。

下面在js中对DOM对象绑定事件的内部调用函数来判断该内部的this指向。

 two.onclick=function(){
    function f1(){
        console.log('2.1 onclick直接绑定且函数内部来调用其他函数,该方法this为:');
        console.log(this)
    };
    f1();
    function f2(){
        console.log('2.2 onclick直接绑定且函数内部来调用其他函数,该方法this为:');
        console.log(this)
    };
    f2();
};

两次的输出结果,对象都是指向的window,因为在内部依旧是window.f1(),window.f2()调用函数,所以输出的this是window。
2.2.3.第三种方式:使用监听事件进行绑定

function typeThree(){
    console.log('3 addEventListener第一次绑定,该方法this为:');
    console.log(this);
}
three.addEventListener('click',typeThree)

此时输出的结果为button,this指向的是DOM对象,监听事件也是像DOm对象中的onclick属性赋值一个函数,此时是DOM对象调用这个函数和,this指向DOM对象。
下面对this谁指向我,我就指向谁的结合例子,依据地址来进行解析。代码如下

function  fn() {
    console.log(this.a );
}
var  obj = {
    a: 2,
    fn: fn
};
var  bar = obj.fn;  //只是把fn赋值给bar,而决定 this 的值的是?
var  a =  "我是全局的a";
bar();

此是输出的结果为‘我是全局的a’,这是为什么呢。我们从根源上说起
首先,我们在js中声明了一个fn()函数,此时fn()函数有一个它自己的地址。

我们对obj对象中的fn属性赋值了一个函数fn(),实际上是将fn()函数的地址赋值给了obj中fn属性。

而后,我们在全局定义了一个bar对象,我们将obj.fn赋值给了bar,因为obj.fn实际上是fn函数的地址,所以此时我们也将fn的地址赋值给了bar。

而,bar()是window对其进行调用,我们又在全局中定义了一个a属性,并将其进行了赋值,所以此时window对象中有a属性,此时的bar()函数与fn()函数的地址一样,调用bar函数可以说成是window调用了bar函数,也可以说成是window调用fn函数,此时window中有属性a,且他的属性值为“我是全局中的a”.
在这里插入图片描述

所以,最终的输出结果为我是全局中的a
2.3:定时器中的this指向

var  obj = {
    a: 42,
    func:function  func () {
        console.log(this.a);
    }
};
setTimeout(obj.func, 1000);

输出的结果为undefined 这是因为setTimeout()调用的代码运行在与所在函数完全分离的执行环境上。这会导致这些代码中包含的 this 关键字会指向 window (或全局)对象。

setTimeout(function(){
    obj.func()
}, 1000);//42
setTimeout('obj.func()', 1000);//42

这两行代码执行的结果都是42

setTimeout('console.log("aaa")', 1000);//aaa

第二种传字符串那种,执行的是一行代码。
2.4.箭头函数中的this指向
箭头函数中的this指向 箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this,即使是call,apply,bind等方法也不能改变箭头函数this的指向

   window.color='red';
    var o={
        color:'blue',
        sayColor:function(){
            return ()=>{console.log(this.color)};
       }
    };
    var sayColor = o.sayColor();
    sayColor();//结果为blue

sayColor中没有color,它将去找上以层继承this,此时this指向o

window.color='red';
    var sayColor=()=>{
        console.log(this.color)
    }
    sayColor();

此时this指向window,函数sayColor的上一级是window,所以此时输出的结果为red

    window.color='red';
var o={
        color:'blue',
        sayColor:()=>{
            console.log(this.color)
     }
    };
    o.sayColor();//red

此时函数o.sayColor的上一级是window,所以输出结果为red 上面那个箭头函数是写在函数里面,而这个箭头函数是函数体

 window.color='red';
    var o = {
    color: 'blue',
    b: () => console.log(this.color),
    c: function() {
        console.log( this.color)
    }
    }
    o.b();  // red
    o.c();  // blue

综合两种如上所示

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值