zoukankan      html  css  js  c++  java
  • javaScript中this的指向?

    javaScript中this对象是在运行时基于函数的执行环境绑定的,在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。

    但在实际中,代码环境复杂,this的指向并非那么直接判断出来。下面来做一下总结。

    1,全局执行环境下的普通函数

    function f1 () {
        console.log(this)
    }
    function f2 () {
        'use strict'
        console.log(this)
    }
    f1() // window
    f2() // undefined

    分为严格模式和非严格模式。非严格模式下等于window,严格模式下为undefined。

    2,事件对象中的this

    this指的是事件对象本身,是指event.target

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <div id="div1">我是一个div</div>
        <script>
          window.id = 'window'
          document.getElementById('div1').onclick = function (){
              alert(this.id) // 输出div1
              
          }
        </script>
    </body>
    </html>

    3,对象中的方法引用

     const foo = {
            bar: 10,
            fn: function() {
               console.log(this)
               console.log(this.bar)
            }
        }
        foo.fn() // this指的是foo
        var fn1 = foo.fn
        fn1() // this指的是window

    4,构造函数中的this

    // this指instance
    function Foo() {
        this.bar = "ceshi"
    }
    const instance = new Foo()
    console.log(instance.bar)
    
    // this指的是 {}
    function Foo(){
        this.user = "ceshi"
    const o = {} return o } const instance = new Foo() console.log(instance.user)

    这里的this之所以不同是由构造返回值是否是对象导致的

    5,丢失的this

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <div id="div1">我是一个div</div>
        <script>
           let getId = document.getElementById
           console.log(getId('div1')) // 报错,报错这是因为document.getElementById方法内的this指向window导致的
           // 修复
           document.getElementById = (function(func){
             return function(){
                 return func.apply(document,arguments)
             }
           })(document.getElementById)
           let getId =  document.getElementById 
           console.log(getId('div1'))
        </script>
    </body>
    </html>

    6,借助bind、Object.prototype.call和Object.prototype.apply改变this的指向

    Object.prototype.call和Object.prototype.apply的是后者参数为数组,前者为多个参数。

    用代码来总结:
    
    const target = {}
    fn.call(target, 'arg1', 'arg2')
    相当于:
    
    const target = {}
    fn.apply(target, ['arg1', 'arg2'])
    相当于:
    
    const target = {}
    fn.bind(target, 'arg1', 'arg2')()

    借助call改变

    const foo = {
        name: 'ceshi',
        logName: function() {
            console.log(this.name)
        }
    }
    const bar = {
        name: 'mike'
    }
    console.log(foo.logName.call(bar)) // mike

    7,其他一些复杂的场景

      const foo = {
                fn: function () {
                    setTimeout(function () {
                        console.log(this) 
                    })
                }
            }
    foo.fn() // this===window

    let,const不会挂在window上面,而var可以

      const a = 999
            let aa = 1000
            var b =1001
            function too(){
                console.log(this.a)
                console.log(this.aa)
                console.log(this.b)
            }
            too()

    对象嵌套中的this

    const person = {
        name: 'ceshi',
        brother: {
            name: 'zhen',
            fn: function() {
                return this.name
            }
        }
    }
    console.log(person.brother.fn())  // zhen

    更复杂的情景

         const o1 = {
                text: 'o1',
                fn: function () {
                    return this.text
                }
            }
            const o2 = {
                text: 'o2',
                fn: function () {
                    return o1.fn()
                }
            }
            const o3 = {
                text: 'o3',
                fn: function () {
                    var fn = o1.fn
                    return fn()
                }
            }
    
            console.log(o1.fn()) // o1
            console.log(o2.fn()) // o1
            console.log(o3.fn()) // undefined

    箭头函数的this提前绑定好

    const foo = {  
        fn: function () {  
            setTimeout(() => {  
                console.log(this)
            })
        }  
    } 
    console.log(foo.fn()) // {fn: ƒ}

    8,通过 call、apply、bind 绑定的情况称为显式绑定;根据调用关系确定的 this指向称为隐式绑定。那么哪一个优先级更高呢?

    function foo (a) {
        console.log(this.a)
    }
    
    const obj1 = {
        a: 1,
        foo: foo
    }
    
    const obj2 = {
        a: 2,
        foo: foo
    }
    
    obj1.foo.call(obj2) // 2
    obj2.foo.call(obj1) // 1

    显式绑定的优先级高于隐式绑定。

  • 相关阅读:
    The first appliaction for "Hello World!"
    zone
    learn to study
    深入理解 Angular 2 变化监测和 ngZone
    看看吧
    生命周期钩子
    一个简单的todo
    依赖注入
    @Output()
    @Input
  • 原文地址:https://www.cnblogs.com/zhensg123/p/12374670.html
Copyright © 2011-2022 走看看