资讯专栏INFORMATION COLUMN

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

golden_hamster / 2117人阅读

摘要:根据各自执行时机的不同来选择采用哪种方案。不可以当作构造函数,也就是说,不可以使用命令,否则会抛出一个错误。不可以使用对象,该对象在函数体内不存在。不能使用箭头函数可以让里面的,绑定定义时所在的作用域,而不是指向运行时所在的作用域。

this是什么
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);
  }
};

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/60428.html

相关文章

  • 如何理解jsthis实际应用需要避开哪些

    摘要:根据各自执行时机的不同来选择采用哪种方案。不可以当作构造函数,也就是说,不可以使用命令,否则会抛出一个错误。不可以使用对象,该对象在函数体内不存在。不能使用箭头函数可以让里面的,绑定定义时所在的作用域,而不是指向运行时所在的作用域。 this是什么 this就是函数内部的关键字 看下面例子理解js中的this // 例子1 function fnOne () { ...

    zebrayoung 评论0 收藏0
  • 如何理解jsthis实际应用需要避开哪些

    摘要:根据各自执行时机的不同来选择采用哪种方案。不可以当作构造函数,也就是说,不可以使用命令,否则会抛出一个错误。不可以使用对象,该对象在函数体内不存在。不能使用箭头函数可以让里面的,绑定定义时所在的作用域,而不是指向运行时所在的作用域。 this是什么 this就是函数内部的关键字 看下面例子理解js中的this // 例子1 function fnOne () { ...

    aaron 评论0 收藏0
  • 如何通过人工智能“避开”内容安全的“”?

    摘要:人工智能技术的初步应用随着网络强国战略思想加强网络内容建设等指导思想的推出和强化,内容安全已经成为互联网企业生存和发展的生命线。 欢迎访问网易云社区,了解更多网易技术产品运营经验。 10月16日,2018年 AIIA人工智能开发者大会在苏州举办。会议邀请了国内外人工智能产业知名人物、国家政府主管部门、行业内顶尖企业、知名学者代表、开源社区优秀贡献团队及个人,共同交流了技术现状趋势、生态...

    _DangJin 评论0 收藏0
  • 从零开始:微信小程序新手入门宝典《一》

    摘要:为了方便大家了解并入门微信小程序,我将一些可能会需要的知识,列在这里,让大家方便的从零开始学习一微信小程序的特点张小龙张小龙全面阐述小程序,推荐通读此文小程序是一种不需要下载安装即可使用的应用,它出现了触手可及的梦想,用户扫一扫或者搜一下即 为了方便大家了解并入门微信小程序,我将一些可能会需要的知识,列在这里,让大家方便的从零开始学习; 一:微信小程序的特点 张小龙:张小龙全面阐述小程...

    whataa 评论0 收藏0
  • 从零开始:微信小程序新手入门宝典《一》

    摘要:为了方便大家了解并入门微信小程序,我将一些可能会需要的知识,列在这里,让大家方便的从零开始学习一微信小程序的特点张小龙张小龙全面阐述小程序,推荐通读此文小程序是一种不需要下载安装即可使用的应用,它出现了触手可及的梦想,用户扫一扫或者搜一下即 为了方便大家了解并入门微信小程序,我将一些可能会需要的知识,列在这里,让大家方便的从零开始学习; 一:微信小程序的特点 张小龙:张小龙全面阐述小程...

    mdluo 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<