当前位置:   article > 正文

promise语法与用法、this指向和this指向修改_改变promise this指向

改变promise this指向

1,this指向

概念:this是运行环境下的一个系统变量,由于this在不同的执行环境下有不同的值,所以在使用this时,多加注意(使用this之前,先打印)

1.1 在全局作用域下,this默认指向window(前端运行环境),(后端运行环境是空对象{})
<script>
       console.log(1, this);//window+文件路径
</script>
  • 1
  • 2
  • 3
1.2 在事件函数中,this指向绑定事件的目标
<body>
    <button id="btn2">点我2</button>
    <script>
        btn2.onclick = function(){
            console.log(2, this);//<button id="btn2">点我2</button>
        }
    </script>
</body>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
1.3 在对象中,this指向它所在的对象本身
<script>
       var zhangsan = {
            name: "张三",
            age: 20,
            eat: function() {
                console.log(3, this);//{name:"张三",age:20,eat: function() {}}
            }
        }
        zhangsan.eat()
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
1.4 在构造函数中,this指向构造函数创建的对象
        function People(name, age) {
            this.name = name;
            this.age = age;
            this.eat = function() {
                console.log(4, this);//{name:"李四",age:20,eat: function() {}}
                //{name:"小明",age:30,eat: function() {}}
            }
        }
        var lisi = new People("李四", 20)
        var xiaoming = new People("小明", 30)
        lisi.eat();
        xiaoming.eat();
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
1.5 在函数嵌套时,内层的函数this不会继承外层函数this的值,会被还原成window

如果内层的函数this不会继承外层函数this的值,内层函数使用箭头函数才能让内层函数的this和外层函数this统一指向

<body>
        <button id="btn5">点我5</button>
</body>
<script>
btn5.onclick = function() {
            console.log(5.1, this)// <button id="btn5">点我5</button>
                // 内层函数直接调用
            function fun() {
                console.log(5.2, this)//window
            }
            fun()
                // 内层函数用计时器调用
            setTimeout(function() {
                console.log(5.3, this)//window
            }, 100)
     // 6, 在函数嵌套时, 如果像让内层函数的this和外层函数this统一指向, 内层函数请使用箭头函数
            console.log(6.1, this)// <button id="btn5">点我5</button>
            var fun = () => {
                console.log(6.2, this)// <button id="btn5">点我5</button>
            }
            fun()
            setTimeout(() => {
                console.log(6.3, this)// <button id="btn5">点我5</button>
            }, 100)
        }
</script>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
1.6 在函数嵌套时,如果想让内层函数的this和外层函数this统一指向,内层函数请使用箭头函数
1.7 在ajax回调函数中,this指向window
        fetch("https://m.douyu.com/api/room/list?page=1").then(function() {
            console.log(7, this)//window
        })
  • 1
  • 2
  • 3
1.8 this指向的修改
  • call(),用函数直接调用call(),第一个参数是this修改后的指向(支持引用类型,如果传入值类型会自动装箱),后边的参数是函数的原始参数,调用call时会直接执行函数
  • apply(),用函数直接调用apply(),第一个参数是this修改后的指向(支持引用类型,如果传入值类型会自动装箱),后边的参数是函数的原始参数所在的数组,调用apply时会直接执行函数
  • bind(),用函数直接调用bind(),第一个参数是this修改后的指向(支持引用类型,如果传入值类型会自动装箱),后边的参数是函数的原始参数,调用bind时不会直接执行函数
        function add(a, b) {
            console.log(8, this, a + b)
        }
        add(3, 4)

        add.call("李四", 5, 6)//8,{"李四"},11

        add.apply(false, [5, 6])//8,Boolean{false},11

        var obj = {
                name: "思聪",
                age: 10
            }
            // 调用bind后会返回一个新的函数
        var newAdd = add.bind(obj, 5, 6)
            // 调用新的函数得到修改后的this
        newAdd()//8,{name:"思聪",age:10}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

总结:

1,this指向的几种情况(谁调用,this就指向谁)

  • 默认情况下,this指向window
  • 事件函数中,this指向事件绑定目标
  • 对象中,this指向对象本身
  • 构造函数中,this指向构造函数创建的对象
  • 嵌套函数中,内层函数默认指向window
  • 嵌套函数中,内层见图函数指向外层函数this

2,call,apply,bind 修改this的异同点

  • call和apply 修改this指向时会立即调用函数,bind修改指向不会立即调用函数,会返回一个新函数
  • call和bind的第二个参数时函数的原始参数写法,apply的第二个参数必须事数组,数组中放的是原始参数

3,call,apply和bind的使用场景

  • call适合在调用函数时修改this指向,直接使用call或apply修改即可
  • bind适合在修改this指向时,不立即调用函数,而是时机成熟时在调用的情况,如:计时器,ajax请求等异步回掉函数的修改

2,Promise

2.1 Promise语法

Promise时ES6新增的一个类,可以解决异步操作上的弊端和问题

  • 新建一个Promise对象,参数是回调函数,回调函数有两个参数,这两个参数分别是resolve,reject,这两个参数也是两个函数
  • 如果在peomise对象中开始一个异步操作,如果异步任务出错,就执行reject函数,传入错误信息;如果异步任务成功,就执行resolve函数,传入成功的数据
  • 用promise对象调用then方法,传入成功的回调函数,对应resolve;传入失败的回调函数,对应reject
  • then方法获取成功回调函数的值和失败回调函数的值,也可以使用下边的链式调用结构,因为then的返回值依然是这个promise对象
  • then函数可以直接传入两个回调函数,一个成功函数,一个失败函数,失败函数是可选的。也就是说,如果异步操作成功的话就执行then函数的第一个成功函数,如果不成功的话就执行then函数的第二个失败函数
var promise = new Promise(function(resolve, reject){
    // resolve 和 reject 也是两个函数, 
    // 在promise对象中开始一个异步操作
    fs.readFile("./1, es6简介.txt", function(err,data){
        // 如果异步任务出错,就执行reject函数,传入错误信息
        if(err)  reject(err.message);
        // 如果异步任务成功, 就执行resolve函数, 传入成功的数据
        else resolve(data)
    })
})
promise.then(function(res){
    console.log(6, res)
})
promise.catch(function(err){
    console.log(6, err)
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
var promise = new Promise(function(resolve, reject) {
    fs.readFile("./data/b.txt", function(err, data) {
        if (err) reject(err.message)
        else resolve(data.toString())
    })
})
//此时异步操作是成功的,所以只打印6.1,而6.2并不打印
promise.then(function(res) {
    console.log(6.1, res);
}, function(err) {
    console.log(6.2, err);
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

注意:

  • 成功的回调函数resolve是必选的,必须在then中传入,失败的回调函数reject是可选的,可以省略
  • then函数获取promise异步结果不管在任何事件,任何位置调用,不管调用多少次,总能拿到异步结果
2.2 Promise用法

promise解决异步操作多层嵌套问题,还能解决多异步任务并发执行的问题

2.2.1 解决异步操作多层嵌套问题

创建一个data文件夹里边有四个txt文件,分别是a.txt,b.txt,c.txt,d.txt,内容分别是:床前明月光,疑是地上霜,举头望明月,低头思故乡

var fs = require("fs");

// 需求:读取data目录下的4各为念中的4句诗,并按顺序拼接
// 方案三:使用promise解决异步操作多层嵌套问题
new Promise(function(resolve, reject) {
        fs.readFile("./data/a.txt", function(err, data1) {
            resolve(data1)
        })
    }).then(function(data1) {
        return new Promise(function(resolve, reject) {
            fs.readFile("./data/b.txt", function(err, data2) {
                resolve(data1 + data2)
            })
        })
    }).then(function(data12) {
        return new Promise(function(resolve, reject) {
            fs.readFile("./data/c.txt", function(err, data3) {
                resolve(data12 + data3)
            })
        })
    }).then(function(data123) {
        return new Promise(function(resolve, reject) {
            fs.readFile("./data/d.txt", function(err, data4) {
                resolve(data123 + data4)
            })
        })
    }).then(function(data1234) {
        console.log(data1234);//床前明月光疑是地上霜举头望明月丢思故乡
    })
    // 缺点:promise虽然解决了多任务嵌套问题,但是以上三种方案存在一个共性弊端,就是多异步任务并发执行的问题
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
2.2.2 解决多异步任务并发执行问题

promise中的异步操作是在new创建直接开始执行的,then函数只是读取异步结果,而不是开始执行异步请求。

// 方案四: 使用promise解决多异步任务并发执行问题
var p1 = new Promise(function(resolve){
    fs.readFile("./data/a.txt",function(err,data){
        resolve(data)
    })
})
var p2 = new Promise(function(resolve){
    fs.readFile("./data/b.txt",function(err,data){
        resolve(data)
    })
})
var p3 = new Promise(function(resolve){
    fs.readFile("./data/c.txt",function(err,data){
        resolve(data)
    })
})
var p4 = new Promise(function(resolve){
    fs.readFile("./data/d.txt",function(err,data){
        resolve(data)
    })
})
//想把多个promise对象合成一个,promise类中提供了两个类方法:all、race
var mergeP = Promise.all([p1,p2,p3,p4])
mergeP.then(function(dataArr){
    console.log(4, dataArr.join(""))
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
2.2.3 把多个promise对象合成一个的方法:all、race
  • all()参数是数组,数组中放多个promise实例,返回一个新的promise对象,使用合并后的对象调用then获取所有promise的结果,是一个数组,数组中数据顺序和all参数顺序保持一致(注意不是按照执行结束的信后顺序排列)
  • all:党合并的所有promise全部完成之后,才会执行then回调,拿到所有结果
  • race:任意一个合并的promise完成之后,立即调用then回调,只能拿到这一个结果
var p1 = new Promise(function(resolve) {
    fs.readFile("./data/a.txt", function(err, data) {
        resolve(data)
    })
})
var p2 = new Promise(function(resolve) {
    fs.readFile("./data/b.txt", function(err, data) {
        resolve(data)
    })
})
var p3 = new Promise(function(resolve) {
    fs.readFile("./data/c.txt", function(err, data) {
        resolve(data)
    })
})
var p4 = new Promise(function(resolve) {
    fs.readFile("./data/d.txt", function(err, data) {
        resolve(data)
    })
})
Promise.all([p1, p2, p3, p4]).then(function(res) {
    console.log(2, res.toString());//2,床前明月光,...低头思故乡
})
Promise.race([p1, p2, p3, p4]).then(function(data) {
    console.log(3, data.toString());//3,低头思故乡
})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

补充:类方法、实例方法

  • 类方法:使用类名直接调用的方法 如:Promise.all() Promise.race()
  • 实例方法:创建出来的对象调用的方法 如:p1.then(), p1.catch()
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/weixin_40725706/article/detail/388470
推荐阅读
相关标签
  

闽ICP备14008679号