前端知识点总结js篇(中)

2023-10-26 17:23:34 浏览数 (1)

Javascript篇

1. 数据类型

代码语言:javascript复制
* 基本数据类型(Number,Boolean,String,null,undefined,symbol(ES6新增),BigInt)
* 引用类型 (Object,Array,Function)

2. 基本数据类型和引用数据类型的区别

代码语言:javascript复制
 * 存储位置不同:
    。基本数据类型存储在栈当中,值与值之间独立存在,修改一个变量不会影响其他变量。
    。引用数据类型存储在堆当中,每创建一个新的引用数值,就会在堆内存当中开辟一个新的空间。
 * 前者复制后,两个变量是独立的,变量保存的是内存地址。

3. let,var和const的区别

代码语言:javascript复制
* let声明的变量只在let命令的块级作用域内有效。
* let命令不存在变量提升,var会发生变量提升
* let声明变量会存在暂时性死区,即变量会绑定某个区域不受外部影响。
* let命令不允许重复定义,但是var可以,重复定义之后后面的值回覆盖前面的值。
* const声明常量,赋值后不可改变,一旦声明必须初始化。
* const也只在声明的块级作用域内有效。变量声明不会提升。
* const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动

4. Null和undefined区别

代码语言:javascript复制
* Null代表空值,代表一个空对象指针;undefined表明变量声明了却未被初始化
* 用typeof判断时,typeof(undefined)能够得到undefined类型,但typeof(null)为object
* 转换时数值不一样,Number(undefined)为NaN,Number(null)为0
* Null一般用于释放内存空间/原型链顶端,当函数没有返回值时,返回undefined

5. 如何判断一个变量是不是数组。

代码语言:javascript复制
* typeof() //判断基本数据类型。但是null判断为object
* Array.isArray() //返回true说明是数组。
* xxx instanceof Array  //返回true说明是数组,可判断复杂数据类型
* Object.prototype.toString.call() //返回[object Array]字符串,说明是数组

6. 数组方法

代码语言:javascript复制
* join() 数组转字符串,默认为逗号分隔符,原数组不变。
* push() 向数组末尾添加一个或多个元素,并返回新的长度。
* pop() 用于删除并返回数组的最后一个元素。
* shift() 用于把数组的第一个元素删除,并返回第一个元素的值。
* unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
* sort() 排序,但是是按照字符编码顺序进行排序的,所以需要实现一个排序函数。
   。 升序return a-b;
   。 逆序return b-a.
* concat() 用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。没有传 
  参的情况下,复制当前数组并返回。
* slice(start,end) 数组截取 ,返回一个新数组,(包含)start到end(不包括)的元素。
* splice(index,howmany,index1….indexX) 数组更新,用于向数组中添加/删除项目,
  然后返回被删除的项目(会改变原始数组)
* indexOf(item,start),从前向后查找,没有返回-1。
* lastIndexOf(item,start)从数组末尾向前查找。

7. Object构造函数的方法

代码语言:javascript复制
* object.assign() 复制一个或多个对象来创建新对象。
* Object.create() 使用指定的原型对象和属性创建一个新对象。
* Object.defineProperty(object , propName , descriptor) 给对象添加一个属性并指定该属性的配置。
- object 对象 => 给谁加  
- propName 属性名 => 要加的属性的名字 [类型:String]  
- descriptor 属性描述 => 加的这个属性有什么样的特性[类型:Object]

* Object.defineProperties() 给对象添加多个属性并分别指定他们的配置。
* Object.entries() 返回给定对象自身的可枚举属性的[key,value]数组。
* Object.freeze() 冻结对象:其它代码不能删除或更改任何属性。
* Object.is() 比较两个值是否相同NaN相等。
* Object.isExtensible() 判断对象是否可扩展。
* Object.isFrozen() 判断对象是否已经被冻结。
* Object.isSealed() 判断对象是否已经密封。
* Object.keys() 返回一个包含所有给定对象自身可枚举属性名称的数组。
* Object.values() 返回给定对象自身可枚举值的数组。

8. js字符串方法

代码语言:javascript复制
* Slice(start,end),字符串的截取。
* Substr(start,length),字符串的截取。
* Substring(start,end) ---以两个参数中较小的一个作为起始位置,较大的一个作为结束位置。
* Split(字符串/正则,length) 字符串转数组。
* CharAt(position)返回指定位置上的字符,如果position<0或大于length,返回空字符串。
* Concat(string) 连接两个或多个字符串,可以直接用 。
* IndexOf(searchString,position)。返回某个指定的字符串值在字符串中首次出现的位置。
* lastIndexOf(searchString,position)。可返回一个指定的字符串值最后出现的位置
* localeCompare(target) 比较字符串,返回比较结果数字。大于target返回正数,小于返回负数,相等返回0。
* match(regexp) 让字符串和一个正则进行匹配。
* replace(searchValue,replaceValue) 对字符串进行查找和替换,并返回一个新字符串。

9. for...of,for...in,forEach和map的区别

代码语言:javascript复制
// for ... of ...   接收数组,具有(iterable)迭代器
// for(item of str) {
//  console.log(item)
// }
代码语言:javascript复制
// for ... in 循环数组时 循环的索引, 循环对象时, 循环的是key
// 速度最慢
// for(item in str) {
//    console.log(item)
// }
代码语言:javascript复制
// forEach  循环遍历数组
// arr.forEach(function(item, index, ar) {
//     console.log("item"   item);
//     console.log("index"   index)
//     console.log(ar)
// })
代码语言:javascript复制
// map 只循环数组,不会对空数组进行检测,不会改变原数组
// var m = arr.map(function(item, index, ar) {
//     return item === "a" ? "dddd" : item;
// })
// console.log(m);

10. JS中的原型链的理解

这篇文章讲解的很详细:juejin.cn/post/693449…

代码语言:javascript复制
* 原型:js中每个对象都有一个与它关联的对象,叫做原型对象。
* 构造函数:用new来调用,就是为了创建一个自定义类
* 原型链:js查找属性得过程中,在自有的属性中找不到就去原型对象中查找,原型对象中找不到,就去原型对象得原型中查找,
  一层一层向上查找的机制,叫做原型链。
代码语言:javascript复制
function Person() {

}

var person = new Person();

console.log(person.__proto__ == Person.prototype) // true
console.log(Person.prototype.constructor == Person) // true
console.log(Object.getPrototypeOf(person) === Person.prototype) // true

11. 闭包

代码语言:javascript复制
* 内部变量访问外部变量的函数。
代码语言:javascript复制
function foo(){
  var a = 2;
  function bar(){
    console.log(a) 
  }
  return bar()
}
var baz = foo()
baz()  //2 这就是闭包的效果
代码语言:javascript复制
* 优点:可以隔离作用域,不造成全局污染。
* 缺点:由于闭包长期驻留内存,则长期这样会导致内存泄露。
* 如何解决内存泄漏: 将暴露全外部的闭包变量置为null。
* 作用: 
   。解决循环变量泄漏为全局变量的问题
   。ES6模块化之前防止变量冲突,通过闭包定义变量方法
   。只能暴露一个接口去访问,私有化属性
   。可以做累加器,函数内部return到外部 // 闭包实现一个count函数,每次调用 1
   。实现柯里化。
      . 将函数内部和函数外部连接起来
      . 防止函数内部变量执行完成后被垃圾机制回收,使其一直保存在内存中

12. this的指向

代码语言:javascript复制
* 在全局作用域内,this指向window
* 在函数中
  。 箭头函数,this指向包裹箭头函数的第一个普通函数
  。 普通函数,如果是直接调用则指向window,如果被obj调用则指向obj,如果通过new的方式创建实例,
     则指向创建出来的实例化对象
  。 使用call、apply、bind,this指向参数中创建的类实例
  。 立即执行函数的话,this指向window

13. new的过程

代码语言:javascript复制
* 创建一个新的空对象
* 新对象的__proto__指向构造函数的prototype
* 新对象赋值给构造函数内部的this上下文,并执行构造函数
* 如果构造函数没有显示返回对象,默认返回this

14. call、bind、apply、的区别

代码语言:javascript复制
* call apply会立即执行,bind不会立即执行,因为她返回的是一个函数。
* 参数不同,apply的参数是数组,call和bind有多个参数。
代码语言:javascript复制
//手写call
Function.prototype.myCall = function(context,...args){
  if(!context && context === null){
    context = window
  }
  let fn = Symbol()
  context[fn] = this //此时this指向foo
  console.log(' context[fn]: ',  context[fn]);
  return context[fn](...args)
}
let obj = {
  a:1
}
function foo(){
  console.log(this)
}
foo.myCall(obj,[1,2,3,4])
代码语言:javascript复制
//手写apply
Function.prototype.myCall = function(context,args){
  if(!context && context === null){
    context = window
  }
  let fn = Symbol()
  context[fn] = this //此时this指向foo
  console.log(' context[fn]: ',  context[fn]);
  return context[fn](...args)
}
let obj = {
  a:1
}
function foo(){
  console.log(this)
}
foo.myCall(obj,[1,2,3,4])

15. 为什么0.1 0.2 !== 0.3

链接juejin.cn/post/689794…

代码语言:javascript复制
* 这个问题有个博主总结的很全面,链接  https://juejin.cn/post/6897949585558208525

16. 事件循环机制

代码语言:javascript复制
a.JS是单线程,防止代码阻塞,我们把代码 (任务) :同步和异步
b.同步代码给is引擎执行,异步代码交给宿主环境(浏览器或者node)
c.同步代码放入执行栈中,异步代码等待时机成熟送入任务队列排队
d.执行栈执行完毕,会去任务队列看是否有异步任务,有就送到执行栈执行,
  反复循环查看执行,这个过程是事件循环(eventloop)


* 同步代码执行完,才会执行事件循环,事件循环包括宏任务和微任务。执行宏任务的前提是清空所有微任务
* 三部分:主线程、宏队列(macrotask)、微队列(microtask)
   * 主线程:scripts标签里包含的内容
   * 宏队列:setTimeout、setInterval、setImmediate、I/O、UI rendering
   * 微队列:promise.then(promise本身是同步,promise.then和promise。catch是
     异步)、process.nextTick,async/await(await后面的的代码)
* Event loop 顺序
   。执行同步代码,这属于宏任务
   。执行栈为空,查询是否有微任务需要执行
   。执行所有微任务
   。必要的话渲染 UI
   。然后开始下一轮 Event loop,执行宏任务中的异步代码

17. 事件委托和事件代理

代码语言:javascript复制
* 原因:添加到页面的事件处理程序数量将直接关系到页面的整体运行性能,因为需要不断与DOM进行交互,
       容易引起重绘重排,事件委托可以减少操作dom的次数。
* 原理:利用冒泡思想。把原本需要绑定在子元素的响应事件委托给父元素,让父元素担当事件监听的职责。

18. promise

(总结不够全面,建议参考es6.ruanyifeng.com/#docs/promi…

代码语言:javascript复制
* 异步编程的一种解决方案。
* promise的api
  promise.then()成功时的回调
  promise.catch()失败时的回调
  promise.finally()无论promise处于什么状态都会执行
* 优点
  。一旦状态(pending,resolved,rejected)改变,就不会再变。
  。可以将异步的操作以同步的流程表达出来,避免回调地域。
* 缺点
  。首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
  。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
  。最后,当处于pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
* promise.all 和 promise.race的区别
  。promise.all  //并发处理多个异步任务,所有任务都执行完成才能得到结果。
  。promise.race  // 并发处理多个异步任务,只有有一个完成就能得到相应结果。
  。promise.allSettled  //所有promise的参数数组发生变更(成功或失败),返回的promise对象才会变更。
  。promise.any //只要参数实例有一个变成fulfilled 状态,包装实例就会fulfilled 状态,如果所有参数实例都变成 rejected 状态,包装实例就会变成 rejected 状态。

19. 深拷贝和浅拷贝

代码语言:javascript复制
* 浅拷贝:假设B复制了A,当A修改时,B也变了。
* 深拷贝:(基本数据类型基本都是深拷贝),深拷贝的对象与原来的对象是完全隔离的,一个对象的修改不会影响另外一个对象。
代码语言:javascript复制
* 实现浅拷贝的方式
 。 ...结构
 。 object.assgin()
代码语言:javascript复制
* 实现深拷贝的几种方式:
 。json.parse(json.stringfy())
 。Object.create() //实现的是深拷贝通过原型链的方式
代码语言:javascript复制
* 函数库 lodash,提供 cloneDeep 实现
* 1.下载相关库**
* npm i --save lodash**
* 2.在相关文件中引入**
* import _ from "lodash"**
* 3.调用 _.cloneDeep() 方法实现深拷贝**

<script>
import _ from "lodash"
var objects = [{ 'a': 3 }, { 'b': 4 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]); 输出false
</script>
代码语言:javascript复制
function deepClone(source){
  const targetObj = source.constructor === Array ? [] : {}
  console.log('source.constructor: ', source.constructor);
  for(let keys in source){
    //判断是否有当前属性 keys = 基本数据类型,{},[]
    if(source.hasOwnProperty(keys)){
      if(source[keys] && typeof(source[keys] === 'Object') ){
        //递归
        targetObj[keys] = deepClone(source[keys])
      }else {
        targetObj[keys] = source[keys]
      }
    }
  }
  return  targetObj
}
let obj = {a:1}
let newObj = deepClone(obj)
console.log(obj.a === newObj.a) //false

20. cookie、sessionStorage和localStorage的区别

代码语言:javascript复制
* cookie的弊端
  。数量和长度的限制
  。安全性问题,如果cookie被拦截,就可以获取所有session信息
  。有些状态不能一直保存在客户端,(为了防止表单重复提交,需在服务端加计数器)

21.js显示类型和隐式类型的转换

代码语言:javascript复制
显示:
Number():Number(null):0;Number(undefined):NaN
parseInt(value, radix):
parseFloat(value):
隐式:
算术运算符:加( )、减(-)、乘(*)、除(/)、取模(%);
逻辑运算符:逻辑与(&&)、逻辑或(||)、逻辑非(!);
字符串运算符: 、 =。
'=='隐式转换

22.防抖和节流

解答来源blog.csdn.net/weixin_5973… 函数防抖: 单位时间内,频繁触发一个事件,以最后一次触发为准。 防抖的实现: 1.声明一个全局变量存储定时器ID。 2.每一次触发交互的时候,先清除上一次的定时器,然后开启本次定时器。

代码语言:javascript复制
  //输入框事件
  let timeID = null
  document.querySelector('input').oninput = function () {
    //1先清除之前的定时器
    clearTimeout(timeID)
    //2.开启本次定时器
    timeID = setTimeout(() => {
      console.log(`发送ajax,搜索的内容是${this.value}`)
    }, 500)
  }

函数节流 单位时间内,频繁触发一个事件,只会触发一次。 使用场景: ajax请求数据;图片懒加载 节流的实现

代码语言:javascript复制
//声明一个全局变量存储触发时间
let lastTime = null
//页面滚动事件
window.onscroll = function () {
  //1.每一次触发 先获取本次时间戳
  let currentTime = Date.now()
  //2.判断当前时间 与 上次触发时间 是否超过间隔
  if (currentTime - lastTime >= 500) {
    console.log(document.documentElement.scrollTop)//获取滚动距离
    //3.存储本次的触发时间
    lastTime = currentTime
  }
}

23.async和await

代码语言:javascript复制
* Async/await作用是用同步方式,执行异步操作。
* Await只能在async函数中使用,不然会报错
* Async函数返回的是一个状态为fulfilled的promise对象,有无值取决于有无return值。(没有则undefined),如果函数内部抛出异常或是返回reject,都会使函数的promise状态变为失败reject(只要不是异常,都不会走catch,哪怕是return false NaN undefined。内部含有未声明变量/函数,函数方法执行出错另当别论)。
* Await后面只有接promise才能实现排队操作。

24.数组去重的方法

1.new Set()实现数组去重 2.利用数组的indexof方法。新建一个空数组,遍历需要去重的数组,将数组元素存入新数组中,存放前判断数组中是否已经含有当前元素,没有则存入。此方法也无法对NaN去重。

代码语言:javascript复制
function removeDuplicate(arr) {
  const newArr = []
  arr.forEach(item => {
    if (newArr.indexOf(item) === -1) {
      newArr.push(item)
    }
  })
  return newArr // 返回一个新数组
}

const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]

3.利用双层循环加数组的splice方法。通过两层循环对数组元素进行逐一比较,然后通过splice方法来删除重复的元素。此方法对NaN是无法进行去重的

代码语言:javascript复制
function removeDuplicate(arr) {
  let len = arr.length
  for (let i = 0; i < len; i  ) {
    for (let j = i   1; j < len; j  ) {
      if (arr[i] === arr[j]) {
        arr.splice(j, 1)
        len-- // 减少循环次数提高性能
        j-- // 保证j的值自加后不变
      }
    }
  }
  return arr
}

const result = removeDuplicate(arr)
console.log(result) // [ 1, 2, 'abc', true, false, undefined, NaN, NaN ]
代码语言:javascript复制
水平有限,如有错误,敬请指正。

0 人点赞