JS-part12.1-this指向 / 改变this指向

this指向

+ 定义:
  => this 是一个使用在作用域内部的关键字
  => 全局很少有, 大部分是在函数内部使用
+ 指向:
  => 全局使用: window
  => 函数使用: **不管函数怎么定义, 不管函数在哪定义, 只看 this 在函数里的调用(箭头函数除外)**
    -> 普通调用(直接调用/全局调用)
      + 函数名(): this -> window
    -> 对象调用
      + xxx.函数名(): this -> 点前面是谁就是谁
    -> 定时器处理函数
      + setTimeout(function(){}, 0): this -> window
      + setInterval(function(){}, 0): this -> window
    -> 事件处理函数
      + xxx.onclick = function(){}: this -> 事件源(绑定在谁身上的事件, 而不是由谁触发)
      + xxx.addEventListener('', function(){}): this -> 事件源
    -> 自执行函数
      + (function(){})(): this -> window
function fn(){
    console.log(this)
}
fn() // 普通调用 this -> window

var obj = {
    // 把 fn 存储的地址赋值给了 obj 的 f 成员
    // 从现在开始, obj.f 和全局变量 fn 指向同一个函数空间
    f: fn,
    name: '我是 obj 对象'
}

obj.f() // 对象调用 this -> obj

// 把 fn 函数当作定时器处理函数使用
setTimeout(fn, 0)  // 定时器处理函数 this -> window
setTimeout(obj.f, 0)  // 定时器处理函数 this -> window

var div = document.querySelector('div')
// 当点击 div 的时候, 执行 obj.f 这个函数
div.onclick = obj.f  // 事件处理函数 this -> div

div.addEventListener('click', obj.f)  // 事件处理函数 this -> div
function fn(){
    console.log(this)
}

fn() // window

setTimeout(function(){
    fn()  // window
},0)

var div = document.querySelector('div')
div.onclick = function(){
    console.log(this)  // div
    fn()   // window
}
var div = document.querySelector('div')
div.onclick = function(){
    function f(){
        console.log(this)
    }
    f()  // window
}
var obj = {
    name: '我是 obj 对象',
    fn: function(){ console.log(this) }
}

obj.fn()  // this -> obj

// 把 obj 里面 fn 成员存储的函数地址赋值给了全局变量 f
// 全局变量 f 和 obj.fn 指向同一个函数空间
var f = obj.fn

f() // this -> window
var obj = {
    name: '我是 obj 对象',
    fn: function(){ 
        console.log(this) 
        function fun(){
            console.log(this)
        }
        fun() // window
    }
}

obj.fn() // obj

改变this指向

改变 this 指向
  + this 有他本身的指向性
  + 不管你本身指向哪里, 我让你指向谁, 你就指向谁
  + 三个方法
    1. call()
    2. apply()
    3. bind()

1. call()

+ 使用方法: 直接连接在函数名后面使用就行
  + 语法:
    -> fn.call()
    -> obj.fn.call()
  + 参数:
    -> 第一个参数, 就是函数内部的 this 指向
    -> 第二个参数开始, 依次给函数传递参数
  + 特点:
    -> 会立即执行函数(不适合用作定时器处理函数或者事件处理函数)
  + 作用: 伪数组借用数组方法
function fn(a, b){
   console.group('fn 函数')
   console.log(this)
   console.log(a)
   console.log(b)
   console.groupEnd()
}

var obj = {
   name: '我是 obj 对象'
}

fn(10, 20)  // this -> window

// 1. call()
// 使用 call 方法去调用 fn 函数, 把函数内部的 this 指向 改变成 obj
// fn.call(obj)   // obj
// fn.call([123, 456])   // [123, 456]
fn.call(obj, 100, 200)

在这里插入图片描述

/*
  小例子
    + call 方法的作用: 伪数组借用数组方法
*/
function f(){
    console.log(arguments)

    // 伪数组用不了数组常用方法
    // 但是数组可以
    // var res = arguments.every(function(t){ return t >= 20 }) // Uncaught TypeError: arguments.every is not a function

    // every() 方法的调用, 需要接收一个函数作为实参
    // arguments.every() 是因为 arguments 没有 every 方法, 所以报错

    // 空数组在调用 every 方法
    // every 里面的 this 指向前面的数组
    // 利用 call 方法来执行数组的 every 函数
    // 第一个参数是 every 里面的 this 指向
    // 原先 every 的 this 指向指向数组的时候, 遍历查看数组
    // 现在 every 的 this 指向 arguments, 遍历查看 arguments
    // call 的第二个参数是给函数传递参数的
    // 函数function(t){return t >= 20})就是传递给 every 方法里面的参数
    var res = [].every.call(arguments, function(item){return item >= 8 })  
    console.log(res)  // true
}

f(10, 20, 30, 40, 50)

2. apply()

+ 使用方法: 就直接连接在函数名后面使用
+ 语法:
    -> fn.apply()
    -> obj.fn.apply()
  + 参数:
    -> 第一个参数, 就是函数内部的 this 指向
    -> 第二个参数, 是一个数组或者伪数组都行, 里面的每一项依次给函数传递参数
  + 特点:
    -> 会立即执行函数(不适合用作定时器处理函数或者事件处理函数)
  + 作用: 可以以数组的形式给某些功能函数传参
    -> Math.max()
// 2. apply()
// 使用 apply 方法调用 fn 函数, 把函数内部的 this 指向 改变成 obj
fn.apply(obj, [1000, 'world'])
/*
  小例子
    + apply 方法的作用: 以数组的形式给某些功能函数传参
*/
var arr = [100, 23, 45, 59, 91]

//     var res = Math.max(100, 23, 45, 59, 91)
var res = Math.max.apply(null, arr)

console.log(res)  // 100

3. bind()

+ 使用方法: 就直接连接在函数名后面使用
+ 语法:
    -> fn.bind()
    -> obj.fn.bind()
  + 参数:
    -> 第一个参数, 就是函数内部的 this 指向
    -> 从第二个参数, 依次给函数传递参数
  + 特点:
    -> 不会立即执行函数
    -> 会返回一个新的函数, 一个已经被改变好 this 指向的函数
  + 作用: 改变事件处理函数或者定时器处理函数的 this 指向 或 传参, 改 this 指向很少用, 一般用来传参
// 3. bind()
// 使用 bind 方法改变 fn 函数的 this 指向
// res 是一个 fn 函数的克隆版, 只不过里面的 this 被锁死了, 指向 obj
var res = fn.bind(obj, 'hello', 'world')
// console.log(res)
res()
 /*
   小例子
     + bind 方法的作用: 改变事件处理函数或者定时器处理函数的 this 指向
 */
var div = document.querySelector('div')

function handler(a, b){
    console.log(this)     // obj
    console(a, b)
}

var obj = { name: '我是 obj 对象' }

// call 和 apply 不合适, 因为还没等到点击呢, 函数就执行了

// 不会把 handler 函数执行, 而是返回一个新的锁死了 this 指向的函数
// var res = handler.bind(obj)
// 调用的是一个被 bind 锁死 this 指向的函数
div.onclick = handler.bind(obj, 100, 200)
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值