Ryan Shang

生死看淡,不服就干

0%

你不知道的JavaScript

JavaScript中总会出现很多有意思的小地方,这里会把我遇到的问题进行总结,并不定期更新。

1. 函数提升和变量提升的优先级?

函数的执行一般有这么几个步骤:

  1. 开辟一个私有作用域
  2. 形参赋值
  3. 变量提升和函数提升
  4. 代码按顺序执行

其中第三步,函数声明的提升优先级要高于变量提升。

2. vue组件的data属性为什么是一个函数返回一个对象而不是直接一个对象?

为了防止vue组件的各个实例之间相互污染各自的数据

3. 为什么0.1 + 0.2 !== 0.3

JavaScript精度处理采用IEEE 754标准,计算机中用二进制来存储小数,而大部分小数转成二进制之后都是无限循环的值,因此存在取舍问题,也就是精度丢失,所以会出现0.1 + 0.2 !== 0.3的情况。

检测方法应该利用Number.EPSILON:0.1 + 0.2- 0.3 > Number.EPSILON

Number.EPSILON 属性表示 1 与Number可表示的大于 1 的最小的浮点数之间的差值。

4. 为什么String、Boolean和Number的基本类型数据可以调用方法?

ECMAScript提供了三个特殊的引用类型:String、Boolean和Number,被称为基本包装类型,与普通引用类型的主要区别就是对象的生存期。

实际上在基本数据类型上调用方法的过程是这样的:

  1. 创建一个基本包装类型的实例
  2. 在实例上调用指定的方法
  3. 销毁这个实例

5. 定义Object的不同方式和区别

先上代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
var o1 = {name: 'o1'};
var o2 = new Object({name: 'o2'});

var M = function () {
this.name = 'o3'
};
var o3 = new M();

var N = class {
constructor () {
this.name = 'o4';
}
}
var o4 = new N();

var P = {name: 'o5'};
var o5 = Object.create(P);

console.log(o1.constructor === Object); // true
console.log(o2.constructor === Object); // true
console.log(o3.constructor === M); // true
console.log(o4.constructor === N); // true
console.log(o5.constructor === Object); // true

console.log(o1.hasOwnProperty('name')); // true
console.log(o2.hasOwnProperty('name')); // true
console.log(o3.hasOwnProperty('name')); // true
console.log(o4.hasOwnProperty('name')); // true
console.log(o5.hasOwnProperty('name')); // false

虽然上面有五种定义方式,但是在我看来,按照返回的对象区分,应该算是三种,o1和o2是一种,o3和o4是一种,o5是一种。

第一种方式构造函数是Object,属性是自己的私有属性

第二种方式构造函数是自己的类,属性是自己的私有属性

第三种方式构造函数是Object,属性是在原型链上的共有属性

6. 深拷贝和浅拷贝的区别

  • 浅拷贝:拷贝前后对象的基本数据不受影响,只拷贝一层,不能对对象中的子对象进行拷贝
  • 深拷贝:对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响