JS知识点--平时视频或做题时发现的知识漏洞(持续更新)

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 = 10
console.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 = 2
console.log(obj)// {a:2,b:{c:1}}
console.log(obj2)// {a:1,b:{c:1}}
obj.b.c = 2
console.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] = 100
console.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 = 2
obj.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):优化了原型链继承的共享问题,但是其只能继承父类的实例属性和方法,不能继承原型属性或者方法。
  • 组合继承(前两组结合):这里涉及多次构造,增加性能开销
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值