如何理解js中的this和实际应用中需要避开哪些坑

看下面例子理解js中的this

    // 例子1
    function fnOne () {
        console.log(this)
    }
    'use strict'
    function fnOne () {
        console.log(this)
    }
    // 例子2
    let a = {
        txt: 'hello world',
        fn: function() {
            console.log(this.txt)
        }
    }
    a.fn()
    window.a.fn()
    // 例子3
    let b = {
        txt: 'hello',
        obj: {
            txt: 'world',
            fn: function(){
                console.log(this.txt)
                console.log(this)
            }
        }
    }
    let c = {
        txt: 'hello',
        obj: {
            // txt: 'world',
            fn: function(){
                console.log(this.txt)
            }
        }
    }
    b.obj.fn()
    c.obj.fn()
    let d = b.obj.fn
    d()
    // 例子4
    function Fn () {
        this.txt = 'hello world'
    }
    let e = new Fn()
    e.txt
    // 例子5
    function Fn () {
        this.txt = 'hello world'
        return {txt:'hello'}
    }
    function Fn () {
        this.txt = 'hello world'
        return [1]
    }
    function Fn () {
        this.txt = 'hello world'
        return 1
    }
    function Fn () {
        this.txt = 'hello world'
        return null
    }
    function Fn () {
        this.txt = 'hello world'
        return undefined
    }
    let e = new Fn()
    e.txt
    // 带有{}或者[]返回值的方法实例化时this指向被改变
    // 例子6
    // 箭头函数与包裹它的代码共享相同的this对象
    // 如果箭头函数在其他函数的内部
    // 它也将共享该函数的arguments变量
    let bob = {
      _name: "Bob",
      _friends: [],
      printFriends: () => {
        console.log(this._name)
        console.log(this)
      }
    }
    let bob = {
      _name: "Bob",
      _friends: [],
      printFriends() {
        console.log(this._name)
        console.log(this)
      }
    }
    
    let bob = {
      _name: "Bob",
      _friends: [1],
      printFriends() {
        this._friends.forEach((item) => {
            console.log(this._name)
        })
      }
    }
    // arguments 对象
    function square() {
      let example = () => {
        let numbers = [];
        for (let number of arguments) {
          numbers.push(number * number);
        }
    
        return numbers;
      };
    
      return example();
    }
    
    square(2, 4, 7.5, 8, 11.5, 21); // returns: [4, 16, 56.25, 64, 132.25, 441]

this的指向

this永远指向的是最后调用它的对象

this的应用

  • 如何改变this的指向 apply call bind

    三者的区别apply和call改变函数this而且是立即执行。bind(es5新加方法注意兼容性)是复制函数,不会立即执行。根据各自执行时机的不同来选择采用哪种方案。
    function Product(name, price) {
      this.name = name
      this.price = price
    }
    function Food(name, price) {
      Product.call(this, name, price)
      // Product.apply(this, arguments)
      this.category = 'food'
    }
    console.log(new Food('cheese', 5).name)
    bind用法和可以解决的问题
    // 解决,从对象中拿出方法定义给新变量,但是希望方法的this值保持不变这时可以用bind来绑定this
    this.x = 9; 
    var module = {
      x: 81,
      getX: function() { return this.x; }
    };
    module.getX(); // 返回 81
    var retrieveX = module.getX;
    retrieveX(); // 返回 9, 在这种情况下,"this"指向全局作用域
    // 创建一个新函数,将"this"绑定到module对象
    // 新手可能会被全局的x变量和module里的属性x所迷惑
    var boundGetX = retrieveX.bind(module);
    boundGetX(); // 返回 81
    
    // bind配合setTimeout()
    function LateBloomer() {
      this.petalCount = Math.ceil(Math.random() * 12) + 1;
    }
    LateBloomer.prototype.bloom = function() {
      window.setTimeout(this.declare.bind(this), 1000);
    }
    LateBloomer.prototype.declare = function() {
      console.log('I am a beautiful flower with ' +
        this.petalCount + ' petals!');
    }
    var flower = new LateBloomer();
    flower.bloom();  // 一秒钟后, 调用'declare'方法
  • 箭头函数的this使用注意事项
    (1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
    (2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
    (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
    (4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。

    (5)不能使用apply/call/bind
    // 箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。下面是另一个例子。
    function Timer() {
      this.s1 = 0;
      this.s2 = 0;
      // 箭头函数
      setInterval(() => this.s1++, 1000);
      // 普通函数
      setInterval(function () {
        this.s2++;
      }, 1000);
    }
    
    var timer = new Timer();
    
    setTimeout(() => console.log('s1: ', timer.s1), 3100);
    setTimeout(() => console.log('s2: ', timer.s2), 3100);
    // s1: 3
    // s2: 0
    // 箭头函数可以让this指向固定化,这种特性很有利于封装回调函数。下面是一个例子,DOM 事件的回调函数封装在一个对象里面。
    var handler = {
      id: '123456',
    
      init: function() {
        document.addEventListener('click',
          event => this.doSomething(event.type), false);
      },
    
      doSomething: function(type) {
        console.log('Handling ' + type  + ' for ' + this.id);
      }
    };
文章来源: 学什么好
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值