0%

快速搞定大厂一面

JavaScript核心原理

image-20211216213550505

数据类型的判断方法

image-20211216214052951

第三种方法最好,Object.prototype.toString 它返回的结果是[object Xxx 就比如object Number]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
'123'==123  true
""==null false
null==0 false
"==0 true
[]==0 true
[]==" true
[]==![] true
null == undefined // true
Number(null) 0
Number('') 0
parselnt('') NaN
parselnt(
{}+10 ='10[object Object]'

'1'+undefined = '1undefined'

image-20211216215624904

image-20211216215633721

image-20211216215927226

Object.valueOf()方法

image-20211216220410734

image-20211216220424019

image-20211216220432142

浅拷贝

自己创建一个新的对象,来接受你要重新复制或引用的对象值。如果对象属性是基本的数据类型,复制的就是基本类型的值给新对象;但如果属性是引用数据类型,复制的就是内存中的地址,如果其中一个对象改变了这个内存中的地址,肯定会影响到另一个对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
第一种方法通过Object.assign方法
let target= o;
let source = {a: { b: 1};
Object.assign(target, source); //target为浅拷贝的对象,source是拷贝的来源
console.log(target); //{a: { b:1}};

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};

第二种方法通过扩展运算符方式

image-20211216222245203

因为a是基本数据类型,只拷贝了值1,但是b是一个对象,拷贝了c:1的地址

因此会有上述结果 也证明了是浅拷贝

如果是深拷贝即便是对象也都不会变 c还是1

1
第三种方法:concat方法也是浅拷贝 (只能用于数据的浅拷贝)使用场景比较局限

image-20211216222513533

slice拷贝数组

image-20211216222657736

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

方法一:JSON.stringfy

image-20211216223420804

用这个方法进行深拷贝的弊端:

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

7.无法拷贝对象的循环应用,即对象成环(obj[key]= obj)

继承方式

1
2
3
4
5
6
7
8
9
10
11
JS的继承到底有多少种实现方式呢?
原型链继承
两个实例使用同一个原型对象的话 内存空间是共享的,当一个发生改变的时候,另外一个也随之进行了变化 图1
构造函数继承(借助call)
它使父类引用的属性不会被共享,优化了第一种继承方式的弊端)但是缺点是只能继承父类的实例属性和方法,不能继承原型属性或者方法
组合继承(前两种的组合)
原型式继承 Object.create()
寄生式继承
寄生组合继承
ES6的extends关键字是用哪种继承方式实现的呢?
寄生组合继承

image-20211216224316214

image-20211217110552271

new关键词的主要作用就是执行一个构造函数、返回一个实例对象,根据构造函数的情况,来确定是否可以接受参数的传递

image-20211217110749763

new关键字执行之后总是会返回一个对象,要么是实例对象,要么是return语句指定的对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function Person(){
this.name = 'Jack';
return {age: 18} //返回与this无关的对象
}
}
var p= new Person();
console.log(p)//{age: 18}
console.log(p.name)// undefined
console.log(p.age)// 18

function Person(){
this.name = 'Jack';
return 'tom'; //不是一个对象
}
var p= new Person();
console.log(p)//{name: 'Jack'}
console.log(p.name)// Jack

apply call bind都可以改变函数func this的指向,call和apply传参的写法不同,apply的第二个参数为数组,call第2个至第n个都是func的传参,bind和这两个都不同,bind改变this的指向但是不是立马执行,call和apply是立马执行

A对象有个getName的方法,B对象也需要临时使用同样的方法那么这时候可以借用A对象的getName方法

![

](https://gitee.com/letter-from-berlin/PictureBed/raw/master/202112171245503.png)

image-20211217124702882

image-20211217124803739

image-20211217124853074

这两个方法是直接返回执行结果,而bind方法是返回一个函数,因此上面直接用eval执行得到结果

image-20211217125007222

实现bind的核心在于返回的时候需要返回一个函数,因此这里的fbound需要返回,但是在返回的过程中,原型链对象上的属性不能丢失,所以这里需要使用Object.create方法将this.prototype上的属性挂到fbound的原型上面,最后再返回fbound

image-20211217125102925

万一真有土豪呢!!!