js原生(复习,外带迟到半个月的Promise)

一.函数定义的方式

  1. 函数声明

    特点:定义前后都能执行

    ​ 为什么前后都能执行?

    因为函数声明的方式:函数提升

    ​ 栗子:

    function fn(){
    	//代码块
    }
    
  2. 函数表达式

    特点:只能在定义后调用才能执行

    var fn = function(){
    	//代码块
    }
    fn()
    

二.new函数,访问原型方法

我们通过一道经典的面试题来了解原型:

function Foo() {
 getName = function () { alert(1) };
 return this;
}

Foo.getName = function () { alert(2) };
Foo.prototype.getName = function () { alert(3) };

//函数表达式
var getName = function () { alert(4) }

//函数声明
function getName() { alert(5) }

//请写出输出结果
Foo.getName() 
getName()  
Foo().getName()  
getName()  
new Foo.getName() 
new Foo().getName()  
new new Foo().getName()  

不要偷看下面的答案哦

===========================================================

===========================================================

下面是答案

===========================================================

===========================================================

答案:2,4,1,1,2,3,3

解析

  1. 第一个就没什么难度吧,直接调用Foo.getName,所以直接弹出 2

  2. 第二个其实难度也不是很大的,可能有些小伙伴会往下面看

    比如:可能打印2,4或者5?

    ​ 但是实际我们仔细看看:

    ​ 下面那个函数表达式=》var getName = function()

    这里的var有一个变量提升,会提升一级。

    所以打印 4

  3. 第三个,重点来了,小伙伴们会不会猜到2或者3?

    其实我刚开始也是猜到2的

    但是呢,第一行就定义了Foo()的函数,所以直接打印的是1

  4. 第四个,其实我们仔细观察一下:

    第四个和第三个其实是一样的:

    第一个声明的Foo()函数里这样声明getName = function()

    函数直接声明表示全局设置,所以这里的this直接指向window

    所以实际上第三个和第四个可以写成这样:window.getName()

    所以打印的是1

  5. 第五个答错的小伙伴们要注意了,

    这里new 了一下Foo.getName()

    但是仍然调用的是Foo.getName,不要被迷惑了

    所以打印 2

  6. 第六个答错的小伙伴们要注意了

    好好复习一下原型链的知识吧?

    在这里实例化了Foo().getName()

    实例化的方法会被分享=>去它的原型上找

    所以这里打印3

  7. 最后一个总不会错的吧?这明明和上一个一样哦?

    举个栗子:

    new new new new new Foo().getName()
    

    它无论new多少次都是new Foo().getName(),

    当然就近原则,他会先new 最近的,从最后一个new 往后解析

    但这不影响它的答案仍然是打印 3

三.JavaScript异步

  1. 同步和异步

    1. 同步:在执行一个请求或者调用功能的时候,没有得到结果是不会继续往下执行,

      ​ 直到返回结果才会往下执行

      ​ 缺点:会造成代码阻塞

    2. 异步:在发送一个请求的时候,不会按照顺序等待,可以继续执行其他代码,之后有信息返回在进行处理,可以提高效率

  2. 异步的应用场景

    1. 数据请求(ajax)
    2. DOM操作:例如:点击事件
    3. 定时器操作:setTimeout,setInterval
    4. and so on…
  3. 管理异步:

    1. 回调函数

      栗子:

      $.ajax({
      	//代码块
      	success:function(res) {
      	   $.ajax({
      	   //代码块
                 success:function(res) {
      				.....
                 }
      	   })
      	}
      })
      

      缺点:容易导致地狱回调

    2. 时隔半个月才想起发布的Promise

      1. 为了解决地狱回调问题,提出Promise管理异步代码

        栗子:

        function request() {
           return new Promise((resolve,reject)=>{
              if(判断条件) {
                 resolve(返值)  //用.then()接收
               }else {
                 reject(返值)  //用.catch接收
               }
           })
        }
        
        //调用
        request().then(res=>{
        	console.log(res)
        }).catch(error=>{
        	console.log(error)
        })
        

        误区:
        这里提醒小伙伴们,Promise不是异步,而是异步处理的一种管理方式,它更趋向同步

    3. async/await

      async/await:用同步方式管理异步代码

      ​ 这两个关键词写到function关键词前面

      ​ 栗子:

      async function fn() {
      
      
      }
      

      使用await必须配合async使用

      栗子:

      async function request() {
         await getList()
      }
      

      new Promise 代码是同步的

      await后面可以跟任意类型的值

      .then是同步的,但是.then中的回调函数是异步的

    4. 下面我们试着做接下来一道异步面试题

      async function async1(){
          console.log('1')   
          await async2() 
          console.log('2')    
      }
      async function async2() {
          console.log('3')       
      }
      console.log('4')    
      
      setTimeout(() => { 
          console.log('5')   
      });
      
      async1()
      
      new Promise((resolve=>{
          console.log('6')  
          resolve()
      })).then(function () { 
          console.log('7')  
      })
      console.log('8')  
      

    ============================================

    ============================================

    不要偷看答案!自己做

    ============================================

    ============================================

    做完了再看答案!

    ============================================

    ============================================

运行结果:

4,1,3,6,8,7,2,5

解析:

  1. 首先打印4,这个毫无疑问吧?

  2. 其次async是微任务,宏任务和微任务

    微任务先执行,所以打印1

  3. 再者,async await2(),这里的代码会推迟到后面执行,

    因为这里有个await,它要等async2执行完之后推迟执行

    async2开始执行,因为它是微任务所以执行打印3

  4. 在这里有些小伙伴说是不是应该打印2了?

    在这里小伙伴们就走入了误区了,

    我们仔细想想await这个任务并不是同步任务但是为什么会一直推迟呢?

    await并不是同步,它只是使得代码能够继续按照顺序执行

    所以,这里会一直推迟到宏任务开始之前

    所以,根据宏任务和微任务,先打印 6

  5. 这里通过Promise打印resole里面的8之后

  6. 同时打印7

  7. 这时候我们仔细想想还有没有微任务执行,不要操之过急

    这么一想,微任务还有一个 2 没有打印,宏任务在后面打印

    所以先打印 2

  8. 最后执行宏任务打印 5,

    到这里,有些小伙伴就有疑惑了:

    这里延迟是不是等于0 啊那岂不是没有延迟就该打印?

    其实不是的,就算写成:

    setTimeout(() => { 
        console.log('5')   
    }0);
    

    它也是最后打印的,表面上我们强制延迟0秒,

    但是在运行的时候,会被强制改成至少延迟4ms,再者setTimeout是个宏任务,

    微任务和宏任务运行时,先执行微任务

    好啦,今天就分享到这里了,各位,晚安~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值