🍉学习JS不得不知的原型原型链、闭包和异步!

891 阅读3分钟

「本文已参与好文召集令活动,点击查看:后端、大前端双赛道投稿,2万元奖池等你挑战!

写在前面

本文主要为笔者对JS学习的总结,介绍原型、闭包和异步这三座JS大山,希望对大家有帮助哦~

一、原型和原型链

谈起原型和原型链我们要清楚一点:
JS是一门基于原型继承的语言。
那么,这里就要介绍一下继承了

1.1 class与继承

这里有一段代码:

// 父类
class People {
  constructor(name) {
    this.name = name
  }
  eat() {
    console.log(`${this.name}eat something~`)
  }
}

// 子类(学生)
class Student extends People {
  constructor(name, number) {
    super(name)
    this.number = number
  }
  sayHi() {
    console.log(`你好,我是${this.name},我的学号是${this.number}`)
  }
}

// 子类(老师)
class Teacher extends People {
  constructor(name, major) {
    super(name)
    this.major = major
  }
  teach() {
    console.log(`我是${this.name},我教授的学科是${this.major}`)
  }
}
let xialuo = new Student("夏洛", 100)
let wanglaoshi = new Teacher("王老师", "数学")
console.log(xialuo.name)
console.log(wanglaoshi.name)
xialuo.sayHi()
wanglaoshi.teach()
wanglaoshi.eat()

运行结果:

image.png

console.log(typeof People) // function
console.log(typeof Student) // function

class实际上是一个函数,它是一个语法糖 再看下面这段代码运行结果:

console.log(xialuo.__proto__) // People{}
console.log(Student.prototype) // People{}
console.log(xialuo.__proto__ === Student.prototype) // true

由此引出了我们的主角:

  • 隐式原型:_proto_
  • 显式原型:prototype

1.2 原型关系

image.png

  • 每个class都有显示原型prototype
  • 每个实例都有隐式原型__proto__
  • 实例的__proto__指向对应class的prototype

1.3 基于原型的执行规则

  • 获取属性xialuo.name或执行方法xialuo.sayHi()时
  • 先在自身属性和方法寻找
  • 如果找不到则自动去__proto__中去查找

1.4 原型链

console.log(Student.__proto__ === People.prototype) // true

image.png

二、作用域与闭包


2.1 作用域

作用域就是一个变量合法的使用范围

image.png
作用域分为

  • 全局作用域
  • 函数作用域
  • 块级作用域(【大括号】ES6新增)

2.2 自由变量

  • 一个变量在当前作用域没有定义,但被使用了
  • 向上级作用域,一层一层依次寻找,直至找到为止
  • 如果到全局作用域都没找到,则报错xx is not defined

2.3 闭包

有两种情况:

  • 函数作为返回值
  • 函数作为参数

image.png

2.4 this

this的取值是在函数执行的时候确定的,不是在定义的时候确定的!

调用的几种方式

  • 作为普通函数
  • 使用call apply bind调用
  • 作为对象方法被调用
  • 在class方法中调用
  • 箭头函数(箭头函数的this始终指向函数定义时的this,而非执行时)

image.png

2.5 作用域相关面试题

this的不同应用场景,如何取值?

  • 作为普通函数
  • 使用call apply bind调用
  • 作为对象方法被调用
  • 在class方法中调用
  • 箭头函数(箭头函数的this始终指向函数定义时的this,而非执行时)

手写bind函数

image.png

实际开发中闭包的应用场景

隐藏数据
比如做一个简单的cache工具
image.png

创建10个a标签,点击每个a标签,弹出对应序号

image.png

三、 异步与单线程


3.1 异步

  • JS是单线程语言,只能同时做一件事儿
  • 浏览器和node.js已支持JS启动进程,如Web Worker
  • JS和DOM渲染公用同一个线程,因为JS可修改DOM结构
  • 异步不会阻塞代码执行
  • 同步会阻塞代码执行

3.2 应用场景

  • 网络请求,如ajax图片加载
  • 定时任务,如setTimeout

image.png

image.png

3.3 Promise的基本使用

创建一个 Promise

const myPromise = new Promise((resolve,reject)=>{

})

通过resolve和reject完成Promise

const myPromise = new Promsie(()=>{
if(true){
 resolve('Promise was fulfilled') 
}else{
 reject('Promise was rejected') 
}
})

用then和catch处理Promise完成的情况

myPromsie.then(result=>{
  
}).catch(err=>{
  
})

3.4 JS异步相关的面试题

异步和同步的区别是什么?

  • 基于JS是单线程语言
  • 异步不会阻塞代码执行
  • 同步会阻塞代码执行

手写用Promise加载一张图片

image.png

最后

本文总结了JS的三座大山,帮助读者快速理解原型,闭包和异步的知识~
如果这篇文章对你有帮助的话,麻烦点赞收藏哟~
GitHub 博客地址: github.com/skyblue309
笔者还有其他专栏,欢迎阅读~
Vue从放弃到入门
玩转CSS之美

后期更文计划

  • 异步进阶及event loop的那些事儿~
  • Grid布局原理及实战
  • vw和vh布局或许会成为新趋势?