欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

前端面试知识点----基础javascript篇(3)

程序员文章站 2022-04-25 13:25:29
...

1.cookie , sessionStrage 和 localStrage

cookie : 用来保存登录信息,大小限制为 4kb 左右。
localStrage : html5 新增 ,用于本地数据存储, 数据不会过期,持久化,一般浏览器大小限制在 5 MB。
seesionStrage : 与 localStrage 类似,保存的数据只在当前会话保存,关闭就会清空。

前端面试知识点----基础javascript篇(3)

2. 0.1+0.2 != 0.3

javaScript在计算0.1+0.2时,会把十进制0.10.2 转换为二进制,但是由于浮点数用二进制表示时是无穷的,
因浮点数小数位的限制而截断的二进制数字,再转换为十进制,就产生误差不相等了

解决方法:把需要计算的数字升级(乘以10的n次幂)成为计算机能够精准识别的整数,计算完成后再降级(除以10的n次幂),但是有时候还会出现精度问题可以用toFixed()number四舍五入为指定小数位,或者重写toFixed()方法,具体参考:http://xieyufei.com/2018/03/07/JS-Decimal-Accuracy.html

0.1*10 + 0.2*10/10 == 0.3 // true

3. 深拷贝和浅拷贝

前言:javaScript的数据类型分为基本数据类型引用数据类型

基本数据类型String ,Number ,Null , Undefined , Booleam , Symbol(es6新增)
变量值存放在栈内存中,可以直接修改,不存在拷贝,好比是无法修改数值为1的值

引用数据类型Object , Function , Math , Date ,RegExp
变量值存放在堆内存中,在栈内存中变量保存的是一个指针,指向堆内存的地址。

浅拷贝:只拷贝到了基本数据类型和引用数据类型的指针(地址),只进行了引用的传递,而没有创建一个新的对象,还是原来的东西,并没有拷贝复制
深拷贝:俩者都拷贝并且复制到了完全的一样的值,在对引用数据类型进行拷贝时,新创建了一个对象,并且完全复制原对象的成员变量

4.定义函数的方法

函数声明

//ES5
function getSum(){}
function (){}//匿名函数
//ES6
()=>{}

函数表达式

//ES5
var getSum=function(){}
//ES6
let getSum=()=>{}

构造函数

const getSum = new Function('a', 'b' , 'return a + b')

5 js数组去重

5.1、遍历循环:使用数组的indexOf
5.2、排序比较:使用数组的 sort(),先排序,后比较相邻的俩个元素的值
5.3、存放Hash对象的方法,将数组元素转化为对象的键名,利用键名的不可重复性来去重。
(存在问题:比遍历快,但内存占用多,就是所谓的:空间换时间)
5.4、若开发环境支持ES6,可以用Set
(ES6中提供了Set数据容器,这是一个能够存储无重复值的有序列表。)

let arr = [1,'1',2,'2',1,2,'x','y','f','x','y','f'];

function unique4(arr){
    return Array.from(new Set(arr));
}

console.log(unique4(arr));

6.一道容易被轻视的前端js题

function Foo() {
    getName = function () { alert (1); };
    return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}

//答案:
Foo.getName();//2
getName();//4
Foo().getName();//1
getName();//1
new Foo.getName();//2
new Foo().getName();//3
new new Foo().getName();//3

此题涉及的知识点众多,包括变量定义提升、this指针指向、运算符优先级、原型、继承、全局变量污染、对象属性及原型属性优先级等等。

题意:

1.首先定义了一个叫做Foo的函数,之后为Foo创建了一个getName的静态属性存储了一个匿名函数,再为Foo的原型对象创建了一个getName的匿名函数。
2.之后又通过函数量表达式创建了一个getName函数,最后声明了一个叫getName的函数。

当我们依次做题:

第一问:

Foo.getName(),访问了Foo的静态属性,答案是:2 。

第二问:

这有俩个坑,一是变量提升,二是函数表达式
变量提升:即所有声明的变量或声明函数都会提升到当前函数顶部。
函数表达式:最大的问题就是会把代码分为俩部分。

运行过程为:

function Foo() {
    getName = function () { alert (1); };
    return this;
}
var getName;
function getName() { alert (5);}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};

getName();//最终输出4,答案为:4 。

第三问:

先执行Foo函数,再调用Foo函数的返回对象的getName属性。
注意:
Foo函数的第一句 getName = function () { alert (1); }; 是一句函数赋值语句,注意它没有var声明,所以先向当前Foo函数作用域内寻找getName变量,没有。再向当前函数作用域上层,即外层作用域内寻找是否含有getName变量,找到了,也就是第二问中的alert(4)函数,将此变量的值赋值为 function(){alert(1)}。

第四问:

直接调用getName函数,相当于window.getName(),因为这个变量已经被Foo函数执行修改了,所以与第三问一样,为 1 。

第五问:

此处考察js的运算符优先级问题。
点的优先级高与new

new (Foo。getName)();

所以,答案为:2 。

第六问:

括号运算符高于new
输出为 3

(new Foo())。getName()

第七问:

同上,答案 3

new ((new Foo())。getName)();
相关标签: 前端