JS基础测试(面经上)
1.原始类型有哪几种?null 是对象嘛?
原始类型:number,string,null,undefined,boolean,symbol,biglnt(symbol,biglnt
是ES6新增的基本数据类型)
null:按照万物皆对象原理null是对象,但是null并不是对象,被判断为是object类型的原因
是在 JS 的最初版本中使用的是 32 位系统,为了性能考虑使用低位存储变量的类型信息,000开头代表是对象,然而null表示为全零,所以将它错误的判断为object。虽然现在的内部类型判断代码已经改变了,但是对于这个 Bug 却是一直流传下来
2. 对象类型和原始类型的不同之处?函数参数是对象会发生什么问题
原始类型存储值,存于栈中,
对象类型栈中存储是指针,值存于堆中;
函数参数是对象时,由于变量中存的是指针,因此函数中对于对象类型中的值的变化也会在全局中体现
3. typeof 是否能正确判断类型?instanceof 能正确判断对象的原理是?
typeof 对于原始值,除了null都能判断出正确的类型
typeof 对于对象来说,除了函数都会显示object,所以说typeof不能准备判断类型
instanceof 可以判断一个实例是否属于当前类,因此可以判断类型
4. 如何正确判断 this?请写出你判断的步骤?
this JS关键词,是一个代词指代不同,需要代码名执行过程中根据上下文判断this的指向
part1:全局域下,this指向window,函数直接调用this指向window,自执行函数this指向window
var a = 0
console.log(this.a); // window
function func(){
console.log(this); // window
}
func()
part2: 对象调用对象函数,谁调用函数this指向谁
var obj = {
name:'张三',
age:30,
say:function() {
console.log(this)
setTimeout(function(){
console.log(this);
},1000)
}
}
obj.say()
part3: 事件处理函数,this指向事件源对象
box.onclick = function(){
console.log(this);
}
part4: 定时器处理函数,this指向事件源对象
setTimeout(function(){
console.log(this);
},1000)
5. == 和 === 有什么区别?
== 会进行隐式的类型转换(两个类型不相同会转换为数字进行比较,如果到字符串级别可以比较了就不会再向下进行转换
=== 全等,就是判断两者类型和值是否相同。
6 .什么是闭包?
定义:闭包的含义:函数在声明时,会保存其所在的词法环境(所有父作用域) 到 scopes 属性里 , 如果是函数作用域, 就称为闭包,简单理解就是 外层函数 是内层函数的闭包,就是内部函数被外部函数以外的变量引用时,就形成了一个闭包
优点:减少全局变量的使用,保证了内部变量的安全,同时外部函数也可以访问内部函数的变量
缺点:浪费内存. 外层函数的作用域不会自动销毁, 会被内层函数保存
作用:在ES6 2015年之前, 用于避免全局变量污染. 利用闭包, 为函数提供私有的变量, 避免全局变量污染
function outter() {
var num = 0; // num 是一个被 outter 创建的局部变量
return function inner() { // inner() 是内部函数,一个闭包
console.log(++num) ; // 使用了父函数中声明的变量
}
}
var a = outter();
a()
7.什么是浅拷贝?如何实现浅拷贝?什么是深拷贝?如何实现深拷贝?
浅拷贝:简单来说浅拷贝就是复制引用,复制后的引用都是指向同一个对象实例,彼此之间的操作互相影响。
var car1 = {name:'保时捷',color:'red',model:'911',price:'120w'}
//浅拷贝:只拷贝指针地址
var car2 = car1;
console.log(car2);
car1['from']='德国'; // 改变car1里的值
car2.color='black'; // 改变car2里的值
console.log(car1);
console.log(car2);
深拷贝:会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
var obj1 ={
name:'张三',
age:30,
hobbies:['吃饭','睡觉','玩游戏']
}
var obj2 = {};
for(var k in obj1){
//判断数据是否是数组,是的话对数组进行深拷贝
if(obj1 instanceof Array){
obj2[k]= [];
for(var i=0;i<obj1[k].length;i++){
obj2[k][i] = obj1[k][i];
}
//如果是值类型直接收值即可
}else{
obj2[k] = obj1[k];
}
}
8.如何理解原型?如何理解原型链?
1.原型:在js中万物皆对象,所以原型又称原型对象,每个对象都有一个__proto__属性,这个属性就是原型对象。另外在js中的函数比较特殊,它有一个prototype属性,是函数的原型对象,称为函数原型。
函数对象的原型:Person.prototype
普通对象的原型:obj.proto
2.原型链:一个对象,通过__proto__或者prototype可以找到它的原型对象,原型对象继续向上查找原型对象,一直到Object对象为至,这样的递归查找过程就是原型链(继承链)。
9.并发与并行的区别?
1.并发:宏观概念,有两个任务A和B,在一段时间内,通过在A和B两个任务间切换,来完成两个任务,这种情况叫并发 (一段时间内多个程序可以运行,一个CPU即可)
2.并行:微观概念,假设CPU有两个核心,那么我们就可以同时完成A,B两个任务。即:同时完成多个任务的情况可以称为并行 (一个时间点内多个程序可以运行,得多个CPU)。
10.什么是回调函数?回调函数有什么缺点?如何解决回调地狱问题?
1.用通俗易懂的白话来说就是一个函数以传参的方式传给另一个函数调用 那么这个函数就叫做是回调函数
2.缺点:容易写出回调地狱(Callback hell,概念:回调函数里面嵌套回调函数) ,及不能使用 try catch 捕获错误,不能直接 return
3.解决方法:promise解决,async/swait解决
回调地狱解决方式
11.进程与线程区别?JS 单线程带来的好处?
一个程序必定包含>=1个进程,一个进程必定包含>=1个线程
进程:是一个动态的过程,是一个活动的实体。简单来说一个应用程序的运算就可以被看做一个进程
线程:是运行中的实际的任务执行者,可以说进程中包含多个可以同时运行的线程。
JS 单线程带来的好处:JS主要是面向浏览器的,因此是和用户实时交互的,如果多线程执行的话,你无法确定同时开始的任务哪个会先结束,以网页加载为例,可能导致网页HTML结构已经加载好,但是CSS样式还未加载完成,导致用户浏览体验差。或者两个线程同时对一个DOM结点进行修改和删除操作,则无法判断以哪个线程为准。
13.new 的原理是什么?通过 new 的方式创建对象和通过字面量创建有什么区别
原理:
1.创建一个空的简单JavaScript对象(即{});
2.链接该对象(设置该对象的constructor)到另一个对象 ;
3.将步骤1新创建的对象作为this的上下文 ;
4.如果该函数没有返回对象,则返回this。
区别:字面量创建对象,不会调用 Object构造函数, 简洁且性能更好
更多详情
14.instanceof 的原理是什么?
1.instanceof 运算符用于测试构造函数的 prototype 属性是否出现在对象原型链中的任何位置
2.解释:假如 A instanceof B,那么A必须是一个对象,B必须是一个合法的js函数(构造函数),在这两个条件都满足的条件下,判断B的prototype属性指向的原型对象(B.prototype)是否在对象A (构造函数的实例对象)的原型链上 (A.proto);如果在,则为true,如果不在,则为false
3.区分构造函数,
4.构造函数的prototype指向原形对象
5.构造函数的实例的 __proto__也指向构造函数的原型对象
6.要判断 p1 instanceof Object 的真假:判断 B 的 prototype 属性指向的原型对象(B.prototype)是否在对象 A 的原型链上。如果在,则为 true;如果不在,则为 false。
原作者:https://juejin.cn/post/6844903821483704327
15.为什么 0.1 + 0.2 != 0.3?如何解决这个问题?
因为两数相加时是转换为二进制在相加,但是0.1和0.2转换时会无限循环,所以0.1 + 0.2 != 0.3
第一种方法
var a = 0.1
var b = 0.2
var c = (a*100 + b*100) / 100
console.log(c);
第二种方法极小常量
var a = 0.1
var b = 0.2
var c = 0.3
var d = Math.abs(a + b - c) < Number.EPSILON
console.log(d); // true
16.什么是标识符?
标识符是指用来标明某个实体的一个符号,在不同的应用环境下有不同的含义。在计算机编程语言中,标识符是用户编程时使用的名字,用于给变量、常量、函数、语句块等命名,以建立起名称与使用之间的关系。
17.JavaScript标识符规范?
1.标识符第一个字符必须是字母、下划线_或美元符号$,其后的字符可以是字母、数字或下划线、美元符号;
2.自定义的标识符不能和 JavaScript 中的关键字及保留字同名,但可以包含关键字或保留字。
3.标识符不能包含空格;
4.标识符不能包含+、-、@、#等特殊字符;
5.由多个单词组成的复合标识符命名主要有两种方式:
一、是使用下划线连接各个单词,每个单词全部小写,例如:dept_name。
二、是使用驼峰式,其中又分大驼峰和小驼峰。大驼峰的格式是每个单词的首字母大写,其余字母小写,例如:DeptName;小驼峰的格式是第一个单词全部小写,第二单词开始的每个单词首字母大写,其余字母小写,例如:deptName。
18.什么是保留字?
指在高级语言中已经定义过的字,程序员不能再将这些字作为变量名、过程名或函数名使用
19.保留字有哪些?
有abstract,double,goto,native,static,boolean,enum,implements,package,super,byte,export,import,private synchronized等
所有保留字链接
以下是必须会的
20 javascript中的数据类型有哪些?
ES5中有6种:Number、String、Boolean、Undefined、Null、Object
ES6新增了Symbol:这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记
bigInt(安全存储、操作大整数)
21 Javascript中所支持的数字函数 (math对象中函数)
1、绝对值
2、大于等于x的最小整数
3、小于等于x的最大整数
4、四舍五入取整
5、正弦函数
6、余弦函数
7、exp() 函数返回以自然数为底,x幂的数
全部无代码实现
有代码实现
22 字符串常用的方法
拼接或截取
1.concat() 连接两个或多个字符串,返回连接后的字符串
2.slice() 提取字符串的片断,并在新的字符串中返回被提取的部分
3.substring() 此⽅法和slice⽅法功能相同都是提取⼀个字符串,并返回提取到的字符串
删除
4.trim() 删除⼀个字符串两端的空⽩字符,并返回删除后的新字符串,不会改变原有字符串
改变字符串
5.toUpperCase() ⽅法没有参数,会将调⽤该⽅法的字符串值转为⼤写形式
split()
6.可以使⽤⼀个指定的分隔符来将字符串拆分成数组,返回⼀个数组
查询字符串
7.charAt() 从⼀个字符串中返回指定的字符
8.includes() 判断字符串中是否包含指定字符,包含则返回true,不包含则返回false
9.indexOf() 判断字符串中是否包含指定字符,如果包含则返回该字符索引的位置(查找到了⽴即返回),如果不包含则返回-1
更多更详细内容
最全面
23 布尔值的转化?(其他转boolea规律)
转化分为两种:
1.可以被强制类型转换为 false 的值
2.被强制类型转换为 true 的值
转换为false的值类型有:undefined,null ,false ,0,NaN , " "
除了以上几种,其他类型均会转换为true。
转换的方法:Boolean(…) 和 ! !( )
var a = 0
Boolean(a) //false
var b = [1,2]
!!b // true
24 什么是null?
javascript中null是JS提供的一种特殊值,表示缺少对象;在javascript中可以使用严格相等运算符来检查null值,其检查语句如“missingObject === null;
25 什么是undefined?
undefined既是JavaScript中的原始数据类型之一,也是一个原始值数据,表示是未初始化的变量或对象属性的值,是全局对象上的一个属性
特点:undefined不可删除,不可重新定义,不可以枚举
26 null和undefined的异同
undefined是未初始化的变量或对象属性的值
null和undefined之间的主要区别是,null表示丢失的对象,而undefined表示未初始化的状态
27 转换和相等性
Js可以做灵活的类型转换,因此其”==”相等运行算也随相等的含义灵活多变,例如下面的结果均为ture.
null == undefined //这两个值被视为相等
“0” == 0 //比较之前字符串转换为数字
0==false //比较之前布尔值转换为数字
“0” == false //比较之前字符串和布尔值都转换为数字
原文链接:https://blog.youkuaiyun.com/pigpigpig4587/article/details/9378117
28 什么是全局变量?
全局变量是指在函数之外定义的变量,它在程序的整个运行周期内都占用存储单元。默认情况下,函数的内部只能获取全局变量,而不能修改全局变量的值
29 什么是局部变量?
在函数内部定义的变量称为局部变量,局部变量只能在定义它的函数内部使用。
30 变量的优先级?
1.局部的优先级要高于全局变量
2.形式参数的优先级高于函数名称
3.形式参数的优先级高于arguments对象
4.形式参数的优先级要高于声明确为赋值的变量
5.形式参数的优先级要低于赋值的变量
原文链接