js 基础

10 篇文章 1 订阅

手写方法案例:链接

import 和 require

import操作符是静态的,import函数式动态的,require是动态的,静态是指编译时加载,动态是指执行时加载。

import既然转码后还是require,为啥还要import???

import、requrie

递归

深度、广度

数据类型

  • 有哪些类型?
  • 类型转换
  • 类型判断
  • 数据在内存中怎么存储?

变量

  • 声明?
  • 变量的作用域

作用域

  • 什么是作用域?
  • 什么是作用域链?
  • 浏览器js解释器对js代码解释执行过程,都做了哪些事情?
  • 参考:
    1、预编译–执行期上下文

闭包

数组、对象、字符串内置方法

  • Object

    1. 创建对象方法???
      使用自定义构造函数创建对象时,发生了什么?
      1、申请内存空间
      2、把this设置成当前对象
      3、设置对象的属性和方法
      4、把this这个对象返回
    2. 克隆一个对象
      Object.assign()
    3. 劫持变量get、set方法
      Object.defineProperty()
    4. 获取可枚举属性
      Object.keys()
    5. 获取所有属性
      Object.getOwnPropertyNames()
    6. 检查对象是否包含某个属性
      Object.getPrototypeOf()
  • Array

    1. join()
      数组元素组成一个字符串,只有以参数为分隔符,默认 逗号
    2. push()、pop()
    3. unshift()、shift()
    4. sort()
      –升序排列数组
      –对数组每个成员调用toString()转型,因此是字符串之间比较,数值比较只会比较第一位。
      –解决上述问题方法,提供一个函数:sort((v1, v2) => v1 - v2)
    5. reverse()
      反转数组项
    6. concat()
      1、会创建一个当前数组的副本;
      2、没有参数:返回副本;
      3、有参数:
      –参数不是数组:将参数添加到副本末尾,返回副本;
      –参数是数组:将数组中成员一次添加到副本末尾,返回副本;
    7. slice()
      -截取数组,返回新数组,不会改变原数组。
      -两个参数,起始位置到结束位置,不包含结束
    8. splice()
      可以实现删除、插入和替换。
      最终都会返回删除项组成的数组,没删除则返回空数组。
      1、删除:两个参数,起始位置,删除个数
      2、插入:三个参数,起始位置,0(删除个数),插入项(可以多项)
      3、替换:三个参数,起始位置,删除个数,插入项(可以多项)
    9. indexOf()
      一个参数时,遍历数组,找到与参数全等(===)的第一个项结束,返回下标,否则返回-1;
      两个参数时,第二个参数表示从哪个下标开始查找,包括这个下标。
    10. forEach()
      遍历数组,成员执行函数,永远返回undefined
    11. some()
      循环数组成员,执行指定函数,满足条件则终止循环,返回Boolean
    12. every()
      循环数组成员,执行指定函数,所有项满足条件则返回true,否则false
    13. filter()
      循环数组成员,执行指定函数,满足条件的项返回,组成新数组。
    14. map()
      循环数组成员,执行指定函数返回的结果,组成新数组。
    15. find()
      循环数组,执行函数,返回第一个满足条件的数组成员。
    16. reduce()
      基本使用
    17. Arrar.of()
    18. Array.from()
      几种遍历方法比较
    • 案例
      1、删除数组中多个成员
      倒叙遍历删除
      filter
      2、数组去重
      最优的方法应该是 利用对象属性key的唯一性去重,可以同时过滤掉NaN,object
      参考几种方法
      3、手写indexOf
  • Set

    1. 用于什么场景
      数组去重,交集,并集。。。

函数

  • 函数调用模式
  1. 函数模式
  2. 方法模式
  3. 构造器模式
  4. 上下文模式
  5. bind() 模式

箭头函数

  • 箭头函数有什么好处?
    使用简单
  • 怎么做到的这种效果?
    这就要说箭头函数的特点了:
    1. 箭头函数没有prototype(原型),所以箭头函数本身没有this
    2. this指向在定义的时候继承自外层第一个普通函数的this,所继承的函数this发生改变,随着改变
    3. arguments不能使用,可以用rest
    4. 不能new,因为没 constructor

函数柯里化

  1. 柯里化:一个函数有多个参数,只传入一个参数,生成一个新函数,新函数接收剩下的参数运行的到结构
  2. 偏函数:一个函数有多个参数,只传入一部分参数,生成一个新函数,新函数接收剩下的参数运行得到结构
  3. 高阶函数:一个函数的参数是一个函数,该函数对这个传入的函数进行加工得到一个函数,这个加工的函数就是高阶函数
  • 为什么用柯里化?

    可以提升性能,柯里化可以缓存一部分能力
    例:1、判断元素
    2、虚拟DOM的render方法

事件循环

  • js为什么需要事件循环(event loop)?
    js是单线程语言,实现多线程和异步需要借助 event loop机制
  • event loop是如何运作的?
    1、首先由三部分组成:调用栈(call stack),消息队列(Message Queue),微任务队列(Microtask Queue)
    2、event loop开始时会从 全局栈一行一行执行js语句
    3、遇到函数,会将函数的调用压入调用栈中,被压入的函数叫帧(Frame),函数返回时会从调用栈中弹出
    4、执行函数中的代码:
    同步代码直接执行,执行完,从调用栈弹出;
    异步代码,分为宏任务和微任务:
    宏任务:回调函数压入消息队列
    微任务:回调函数压入微任务队列
    5、全局栈代码执行完,调用栈为空时,会立即执行微任务队列中的任务,并且新加入的微任务也会一起执行,微任务队列为空时,再去执行宏任务队列的任务。依次循环,直到微任务队列,消息队列,调用栈都为空,结束。
  • 宏任务
    setTimeout、 setInterval、 Ajax、 DOM事件
  • 微任务
    Promise async/await
  • 案例:
    1、事件循环在 vue 中应用???

JSON

  • 案例:
    1. 手写JSON.parse、JSON.stringify
    2. 不使用JSON.stringify将对象转换为JOSN格式字符串???

原型、原型链、继承

  • 原型带了什么?
    1、在js中,都是对象,作者想把对象关联起来,所以引入了 new 这个关键字,通过 new 一个原型对象得到一个实例对象。但是js中又没有 类(class) ,因此 new的是构造函数(constructor)
    2、用 构造函数实例对象 又有另外一个问题:无法共享属性和方法,即 得到的对象都是独立的,会在内存中开辟新的空间,浪费内存资源
    3、解决问题:
    作者设计了 prototype 属性,是一个对象,里面存的是实例对象需要共享的 属性和方法,不需要共享的放在构造函数里

  • 原型链
    在这里插入图片描述
    阮一峰Javascript继承机制的设计思想

  • 案例
    1、原型方法重写
    2、手动实现 instanceof 方法

    function mockInstanceof(obj,constructorFn){ 
        let pro = obj.__proto__ 
    	while(pro) {
    		if(!pro) {
    			return false;
    		} else if(pro === constructorFn.prototype) {
    			return true;
    		} else {
    			pro = pro.__proto__
    		}
    	}
    }
    mockInstanceof([], Array)
    

继承

js8中继承方法
1. 原型链继承
缺点:
多个实例数据公用,不独立,会相互污染;
实例化子类没办法传参给父类
2. 使用构造函数继承
不使用原型
缺点:
只能继承父类实例的属性和方法,不能继承原型的属性和方法;
不能复用,因为每一个实例都会有父类的实例的副本,影响性能;
3. 组合继承(原型链+构造函数)
原型链实现原型属性和方法的继承,构造函数实现实例的属性和方法的继承
缺点:
实例中的属性会屏蔽原型对象上的属性;
4. 原型式继承
缺点:
原型链继承多个实例的属性,引用类型属性指向相同,存在数据污染可能;
没办法传参数;
5. 寄生式继承
实际就是原型式继承增强,扩展了给构造函数新增属性和方法的功能
缺点:同原型式继承
6. 寄生式组合继承(寄生式+构造函数)
最优的解决方案
7. 混入方式继承多个对象
8. extends关键字
ES6继承方式,实际就是 寄生式继承的封装

ES5 和 ES6 区别:
ES5是先创建子类实例对象,将父类属性和方法通过this添加到自类中;
ES6是先创建父类实例对象 this,再用子类的构造函数修改this指向自己。因此必须先调用super方法。

Promise

new Promise((resolve, reject) => {
  reject('err')
})
  .then(
    res => {
      console.log('fulfilled', res)
    },
    err => {
      console.log('rejected', err)
    }
  )
  .catch(err => {
    console.log('rejected catch', err)
  })
  .finally(() => {
    console.log('finally', 1)
  })
  // 结果:
  // rejected err
  // finally 1
  • 案例:
    1、实现一个promise?
    三个状态、三个回调函数、两个函数入参
    参考手动实现
    2、promise是怎么实现异步的???
    3、promise中断调用链?
    在then/catch 的最后一行返回一个永远 pending 的 promise 即可:
    return new Promise(() => {})
    
    4、中断promise?
    promise无法终止,中断后依然会执行返回结果,只是这时候我们不再关心结果。
    使用 ***Promise.race([…])***,只要有一个返回就结束不论then/catch。

async\await

  • async
    async 定义的函数默认返回一个Promise对象resolve的值,因此有一个then方法,then的入参即为函数返回值。

    async function fn() {
      return 'fn 1'
    }
    fn().then(res => {
      console.log('async', res)	//async fn 1
    })
    
  • await
    await 关键字 只能放在 async 函数内部,作用是获取Promise函数中resolve或者reject的值
    如果不是一个Promise的返回值,则会按照同步程序返回值处理

  • 是如何实现异步请求的?
    async/await 是一个语法糖,是基于PromiseGenerator 封装实现的。
    利用 Generator 这个生成器的特点:yieId 这个关键字可以将函数执行流挂起,然后通过一个 next方法 主动切换状态,获取结果。 封装的关键点是让这个next方法自动执行。next执行返回的结果为{value:value, done: true/false},done 代表的是所有 Generator 中的语句执行完毕,因此我们可以提供一个方法,递归执行 next方法 ,返回最终的结果。
    Promise/async/Generator实现原理解析

setTimeout、setInterval

  • setTimeout
    只在指定时间后执行一次
    清除 clearTimeout()

  • setInterval
    以指定时间为周期循环执行
    clearInterval()
    ⚠️少用,有很多缺陷
    1、无视代码错误

    function a() {
      try {
        cnosole.log('拼写错误 console')
      } catch (e) {
        console.log('err')
      }
    }
    setInterval(a, 1000)
    // 每隔1s输出 err
    

    2、无视网络延迟

    function testSetInterval() {
      let i = 0
      const start = Date.now()
      const timer = setInterval(() => {
          i++;
          i === 2 && clearInterval(timer)
          console.log(`${i}次开始`, Date.now() - start)
          for(let i = 0; i < 900000000; i++) {}
          console.log(`${i}次结束`, Date.now() - start)
      }, 100)
    }
    testSetInterval()
    // 第1次开始 105
    // 第1次结束 694    
    // 第2次开始 695
    // 第2次结束 1263
    // 问题:为什么第一次结束 和第二次开始只隔了1ms
    // 原因:无视网络延迟,不会管上一次还行结果,定时将要执行的函数放入 异步队列
    

    处理可能的阻塞:

    function foo(){
      setTimeout(foo, 1000)
    }
    foo()
    

    关于这两定时器清除问题:

    返回的都是一个id,代表顺序,从1开始,清除之后id不会被清除。
    是否有必要清除?
    答案是看需求,如果只有一个,不清除没什么影响,如果是用setTimeout模拟setinterval,则需要根据实际情况清除。

DOM方法

BOM方法

BOM即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window

window常见事件
  • setTimeout、setInterval
  • location
    用于获取或设置窗体的 URL: protocol://host[:port]/path/[?query]#fragment
    location.href ------ 获取或者设置整个URL
    location.host ------ 返回主机(域名)www.itheima.com
    location.port ------ 返回端口号 如果未写返回空字符串
    location.pathname ------ 返回路径
    location.search ------ 返回参数
    location.hash ------ 返回片段 #后面内容常见于锚点链接
    location.replace ------ 设置整个URL,不记录历史
  • navigator
    userAgent属性,返回 客户机信息。主要用于判断客户机是什么终端。
  • history
    back() 返回上一页
    forward() 前进一页
    go(n) n :正数前进n页,负数返回n页
    pushState(state, title, url)
    replaceState(state, title, url)
    state:一个与指定历史记录相关联的状态对象,当popstate事件触发时,会把该对象传入回调函数。如果不需要用到,可以传null。
    title:页面的标题。但当前大多数浏览器都不支持或忽略这个值。可以传null。
    url:添加或修改的history的网址。为了安全性,必须保持与当前URL同一个域。
    简而言之,两个方法的区别只是pushState添加一个最新的历史记录,而replaceState则是把当前的页面的历史记录替换掉。他们最大的特点是添加或替换历史记录后,浏览器地址栏会变成你传的地址,而页面并不会重新载入或跳转。

函数式编程、面向对象

  • 函数式编程 用来描述数据(函数)之间的映射,相同的输入始终要得到相同的输出(纯函数)。
  • ***面向对象***核心是对象,通过 封装、继承、多态 来演示事物事件的联系。

缓存

localStorage、sessionStorage 存储大小都是5M左右,不同浏览器无法共享其中的信息。

  • localStorage
    生命周期是永久,需要手动清除。
  • sessionStorage
    生命周期是页面或浏览器,关闭了就会清除。
    cookie、session比较

跨域

封装ajax,http,跨域

参考

http

  • 是什么
    超文本传输协议,是互联网中应用最为广泛的网络协议,是基于 TCP/IP 协议簇来传递数据。

  • 原理?
    1、http建立连接
    其实就是建立 TCP连接 ,???
    因为http这个协议传输层使用的是 TCP协议。

    既然 http 是基于 TCP/IP 协议簇传递数据,那么我们必须了解这个 TCP/IP协议簇
    四层模型: 传输层、网络层、链路层、物理层
    工作原理:
    数据发送端是一层一层封装数据,数据接收端一层一层拆封,最后应用层获得数据。

    TCP连接过程:就是我们常说的 3次握手:
    客户端发送位码要求连接服务端;
    服务端收到并确认联机信息后同意客户端来连接;
    客户端收到通知并校验再次发送请求;
    服务端收到请求确认并建立连接成功。

    2、客户端发送请求
    就是http请求,请求报文实际就是TCP数据体。
    2.1 http请求报文结构: 请求行、请求头、空行(表示请求体开始)、请求体、空行(表示请求体结束)
    2.2 请求实例

    3、服务端响应请求
    3.1 响应报文结构: 响应行、响应头、空行(表示响应体开始)、响应体、空行(表示响应体结束)
    3.2 响应实例
    3.3 响应状态码:

    4、断开连接
    在服务器响应完毕后,http一次会话就结束。
    4.1 短连接: TCP断开连接,再请求需要重新建立TCP连接。
    4.2 长连接: TCP不断开连接,允许http多次会话,http永远都是一次请求响应会话就结束,不存在长连接之说。
    请求头设置:Connection:keep-alive 表示建立TCP长连接。服务端也可以设置 close 拒绝长连接。
    长连接优缺点:看http请求次数,以及网站需要的资源量。
    4.3 断开连接过程: 四次挥手

  • http缺点
    明文且不能保证完整性,被HTTPS代替。

  • https和http区别
    https

详细内容参考

http、https、CDN…

数据请求 Ajax

  • 原理
    通过 XmlHttpRequest 对象来向服务器发异步请求。对该对象方法和属性的扩展,实现Ajax。

  • 案例:
    实现一个Ajax请求?

    封装ajax,http,跨域

XmlHttpRequest

  • 方法
    1、open()
    创建一个XmlHttpRequest 对象,需要几个参数:
    method:指定用来发送请求的http方法,常用GET,POST,还有,PUT,DELETE或HEAD;
    uri:请求服务器地址;
    async:异步还是同步请求,默认 异步(ture);
    XmlHttpRequest 有个属性 readyState,值为4,将对responseText、responseXML、status和statusText 这些属性复位至初始值,值为 1,则复位完成,同时我们准备好了一个请求。
    2、send()
    readyState 值为 1时,才可以调用send方法,将请求发送至服务器。
    当async参数为true时,send()方法立即返回,从而允许其它客户端脚本处理继续。在调用send()方法后,XMLHttpRequest对象把readyState的值设置为2(发送)。当服务器响应时,在接收消息体之前,如果存在任何消息体的话,XMLHttpRequest对象将把readyState设置为3(正在接收中)。当请求完成加载时,它把readyState设置为4(已加载)。对于一个HEAD类型的请求,它将在把readyState值设置为3后再立即把它设置为4。
    3、setRequestHeader()
    该setRequestHeader(DOMString header,DOMString value)方法用来设置请求的头部信息,Content-Type。当readyState值为1时,你可以在调用open()方法后调用这个方法;否则,你将得到一个异常。
    4、getResponseHeader()
    getResponseHeader(DOMString header,value)方法用于检索响应的头部值。仅当readyState值是3或4(换句话说,在响应头部可用以后)时,才可以调用这个方法;否则,该方法返回一个空字符串。
    5、getAllResponseHeaders()
    该getAllResponseHeaders()方法以一个字符串形式返回所有的响应头部(每一个头部占单独的一行)。如果readyState的值不是3或4,则该方法返回null。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值