JS知识点--平时视频或做题时发现的知识漏洞(持续更新)
发布日期:2021-05-07 09:21:34 浏览次数:19 分类:精选文章

本文共 4377 字,大约阅读时间需要 14 分钟。

1.如果编写了非有效的js时,例如把return写成retrun,会抛出ReferenceError

2.使用JSON.parse()方法,可以将JSON字符串解析为JavaScript值

3.对于一个var name如果只声明变量而未初始化,则会打印undefined。而如果用let/const关键字声明变量且未初始化,则它被引用时会抛出ReferenceError,此情况被称为“暂时性死区”

4.在ES2020中,通过#号可以给class添加私有变量,即在class外部无法获取该值,如果尝试输出,则会抛出SyntaxError

5.SyntaxError:Javascript引擎发现了不符合语法规范的代码

ReferenceError:当对变量/项的引用被破坏或不存在时,将引发此错误.

6.在使用typeof判断null的数据类型时,会显示为object类型,这是存在的一个小问题,特殊记一下。此外typeof判断引用类型时,只能分辨出object和function两种类型

7.三种数据类型检测方法比较:

  • instanceof可以准确判断复杂引用数据类型,但是不能正确判断基础数据类型
  • typeof可以判断基础数据类型(null除外),但是引用数据类型中,除了function类型外,其他的也无法判断
  • Object.prototype.toString(),或者Object.prototype.toString.call(xxx),最终返回[Object 数据类型],注意数据类型的首字母大写,如[Object Number]

8.数据类型转换:

a.强制类型转换 6种

  • Number():对于布尔型true和false分别被转化成1和0;
    数字则返回自身null返回0undefined返回NaN;
    对于字符串,如果字符串中只包含数字则将其转换为十进制;如果字符串中包含有效的浮点格式将其转换为浮点数值;如果是空字符串将其转换成0;如果不是以上格式的字符串则返回NaN
    symbol型则抛出错误
  • parseInt()
  • parseFloat()
  • toString()
  • String()
  • Boolean():除了undefined,null,false,’’,NaN,0转换出来的是false,其余都是true

b.隐式类型转换 5种

  • 逻辑运算符&&、||、!
  • 运算符+、-、*、/
    ‘+’号操作符不仅可以用作数字相加,也可以用于字符串拼接
    如果其中有一个是字符串,另外一个是undefined、null或布尔型,则调用toString()方法进行字符串拼接
    如果其中有一个是数字,另外一个是undefined、null、布尔型或数字,则会将其转化成数字进行加法运算
    如果其中一个是字符串,一个是数字,则会按照字符串规则进行拼接
    如果**‘+’两边都为字符串**,则将得到经过加法运算后的字符串
  • 关系运算符>、<、>=、<=
  • 相等运算符==:
    如果类型相同无需进行类型转换;
    如果其中一个操作值为null或者undefined,那么另外一个操作值必须为null或者undefined才会返回true,否则都返回false
    如果其中一个是symbol类型,那么返回false
    两个操作值都为stringnumber类型,那么就会把字符串类型转换为number
    如果一个操作值为boolean,那么转换为number
    如果一个操作值为object,且另一方为stringnumber、或者symbol,就会把object转换成原始类型再进行判断
  • if/while条件

9.object转换规则

  • 如果部署了[symbol.toPrimitive]()方法,优先调用再返回
  • 调用valueOf(),如果转换为基础类型则返回
  • 调用toString(),如果转换为基础类型则返回
  • 如果都没有返回基础类型,会报错

10.JS中实现浅拷贝的方法:4种

浅拷贝即只能拷贝一层对象,如果出现对象的嵌套,则无能为力

  • object.assign:object.assign是ES6中object的一个方法,该方法可以用于JS对象的合并等多个用途,其中一个用途就是可以浅拷贝。语法为object.assign(target,...sources)

示例代码:

let target = {   }let source = {   a:{   b:2}}object.assign(target,source) // 拷贝的是引用数据类型,即拷贝的是地址console.log(target) // {a:b:10}source.a.b = 10console.log(source) // {a:b:10}console.log(target) // {a:b:10}
  • 扩展运算符方法:利用JS扩展运算符,在构造对象的同时完成浅拷贝的方法。语法为let cloneObj = {...obj}

示例代码:

let obj = {   a:1,b:{   c:1}}let obj2 = {   ...obj}obj.a = 2console.log(obj)// {a:2,b:{c:1}}console.log(obj2)// {a:1,b:{c:1}}obj.b.c = 2console.log(obj)// {a:2,b:{c:2}}console.log(obj2)// {a:1,b:{c:2}}
  • concat拷贝数组:只能用于数组的拷贝

示例代码:

let arr = [1,2,3]let newArr = arr.concat()newArr[1] = 100console.log(arr)// [1,2,3]console.log(newArr)// [1,100,3]
  • slice拷贝数组:仅针对数组对象,语法为arr.slice(begin,end),返回一个新的数组对象,不会更改原数组

11.手工实现一个浅拷贝

  • 对基础类型做一个最基本的浅拷贝
  • 对引用类型开辟一个新的存储,并且拷贝一层对象属性

代码示例:

const shallowClone = (target) => {   	if(typeof target === 'object' && target !== null){   		const cloneTarget = Array.isArray(target)?[]:{   }		for(let prop in target){   			if(target.hasOwnProperty(prop)){   				cloneTarget[prop] = target[prop]			}		}		return cloneTarget	}	else{   		return target	}}

12.JS中实现深拷贝的方法:

深拷贝的原理为:将一个对象从内存中完整的拷贝出来一份给目标对象,并从堆内存中开辟一个全新的空间存放新对象,且新对象的修改并不会改变原对象,二者实现真正的分离

  • 乞丐版(JSON.stringify):是目前开发过程中最简单的深拷贝方法

示例代码:

let obj = {   a:1,b:[1,2,3]}let str = JSON.stringify(obj)let obj2 = JSON.parse(str)console.log(obj2) // {a:1,b:[1,2,3]}obj.a = 2obj.b.push(4)console.log(obj) // {a:2,b:[1,2,3,4]}console.log(obj2) // {a:1,b:[1,2,3]}

JSON方法中存在的缺陷:

1.拷贝的对象的值中如果有函数、undefined、symbol 这几种类型,经过 JSON.stringify 序列化之后的字符串中这个键值对会消失;
2.拷贝 Date 引用类型会变成字符串;
3.无法拷贝不可枚举的属性;
4.无法拷贝对象的原型链;
5.拷贝 RegExp 引用类型会变成空对象;
6.对象中含有 NaN、Infinity 以及 -Infinity,JSON 序列化的结果会变成 null;
7.无法拷贝对象的循环应用,即对象成环 (obj[key] = obj)。

  • 改进版,通过递归实现
const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)const deepClone = function (obj, hash = new WeakMap()) {     if (obj.constructor === Date)   return new Date(obj)       // 日期对象直接返回一个新的日期对象  if (obj.constructor === RegExp)  return new RegExp(obj)     //正则对象直接返回一个新的正则对象  //如果循环引用了就用 weakMap 来解决  if (hash.has(obj)) return hash.get(obj)  let allDesc = Object.getOwnPropertyDescriptors(obj)  //遍历传入参数所有键的特性  let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc)  //继承原型链  hash.set(obj, cloneObj)  for (let key of Reflect.ownKeys(obj)) {        cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ? deepClone(obj[key], hash) : obj[key]  }  return cloneObj}

13.继承:继承可以使子类别具有父类的各种属性和方法

当前一共有6种继承方法:

  • 原型链继承:缺点为共享问题。它们的内存空间是共享的,当一个发生变化的时候,另外一个也随之进行了变化。
  • 构造函数继承(借助call):优化了原型链继承的共享问题,但是其只能继承父类的实例属性和方法,不能继承原型属性或者方法。
  • 组合继承(前两组结合):这里涉及多次构造,增加性能开销
上一篇:JS数据结构--栈--常见操作
下一篇:【HDU】3085&【YBT高效进阶】1基础算法/5广度优先搜索/6逃离噩梦

发表评论

最新留言

感谢大佬
[***.8.128.20]2025年03月20日 21时23分08秒