内置类型
js内置类型有哪些?
js中有七种内置类型,而七种内置类型又分为两大类型:基本类型和对象。
基本类型中包括:null,undefined ,string,int,boolean,symbol
typeOf区分类型的原理
在js中, null和object是两种数据类型,但是使用typeof时统一认为是object,是因为不同的对象在底层都表示为为二进制,在JavaScript中前三位都为0的话就会判定为object,null用二进制表示为全0,自然前三位也是0,所以执行typeof的时候会自动返回object。可以使用instansof来区分null和object,instanceof是使用原型链来判断的。
类型转换
显式转换
通过手动进行类型的转换叫做显式转换;
转换为数字类型:parseint(),Number(),parsefloat()
转换为字符串类型:toString(),string()
转换为波尔值:boolean()
隐式类型转换
某些情况下js我们不主动提供数据转换,js也会在内部进行数据转换
isNaN -会调用Number()去检测是否能转换并且返回波尔值;
递增递减符号 -会将所有即将执行这个操作的转换为数字之后在执行递增递减
加减乘除 -会将所有的非数字的类型调用number()去做类型转换
逻辑运算符 -调用boolean()去做类型转换
比较运算符 -如果一方是int会调用number(),如果一方是字符串则调用tostring()
== 相等运算符 -与上述差不多,null与undefined返回true
作用域
JavaScript作用域的理解
作用域就是变量和函数可访问的范围,也可以说是作用域控制着变量和函数的可见性和生命周期,其中包括全局作用域和局部作用域。
什么是作用域链
在寻找变量时会在当前执行上下文中寻找该变量,当未找到时会去父级的执行上下文中去寻找变量,一直寻找到全局变量,这个过程就叫做作用域链。
let和const的块级作用域
在ES5中只有全局作用域,在ES6中引入了块级作用域,一对{}或for,if为一个块级作用域。
let和const只在块级作用域中可被访问并且不存在变量提升,也不能够被重复声明。
var,const和let对比
只有var存在变量提升,只有var是全局作用域的声明,var和let声明时不是必须要赋值,只有var能够重复定义(并不提倡
new的过程
首先创建一个新对象并且继承构造函数的原型,然后将参数传入构造函数内执行构造函数,也可称为改变构造函数内部this的指向。
执行上下文
对于执行上文的理解
在JavaScript代码执行之前,js引擎会做一个准备工作,这个工作就称为执行上下文;执行上下文分为三大类:全局执行上下文,函数执行上下文,eval执行上下文。
闭包
对于闭包的看法,为什么要使用闭包,闭包原理以及应用场景
概念:在JavaScript的执行过程中,只有函数内部的子函数才能访问函数内部的变量,所以闭包可以理解为定义在函数内部的一个子函数,可以说闭包就是将函数内部变量与外部连接起来的一座桥梁。 ----转自阮一峰
用途:可以访问到函数内部的变量;还可以将这些变量永远保存在内存中;
原理:函数执行的时候是依赖函数定义时的作用域链,即js函数执行时访问的是该函数的作用域链,来访问本无法访问的变量,当在函数执行上下文操作之后,函数会销毁,而其变量会储存在变量中。
闭包的问题以及优化
由于闭包中的变量是储存在内存中,对内存影响较大,如果使用不当会造成内存泄漏,严重影响网页的性能,解决办法是在函数执行结束之后将无用的局部变量全部删除。
this指向
如何确定this指向
全局作用域下的this ---指向Window对象
构造函数时,this指向实例的对象
对象方法调用时,this指向调用的对象
通过事件绑定的方法中,this指向绑定事件的对象
定时器函数,计时器函数,this指向全局window函数
改变this指向的方法
function.call(调用者,函数参数);
function.apply(调用者,[数组方式来传函数参数])
function.bind(调用者)(函数参数)
介绍箭头函数
由于箭头函数不绑定this,他会捕获在她定义的位置上下文的this值,作为自己的this值。
apply,bind,call并不会改变箭头函数中this的指向。
bind的实现方式
function test (name){
console.log(name,this.id)
}
function bind1( func , obj){
var paramsArr = [].slice.call(arguments,2)
return function(){
func.apply(obj,paramsArr.concat([].slice.call(arguments,0)))
}
}
var object = {id:'123'}
var test1 = bind1(test,object)
test1('ssc')
原型,继承
对原型链的理解,原型链图
原型链:从一个实例对象向上寻找有一个构造函数的原型对象,在构造函数的原型对象上又有构造他的原型对象,原型链最顶端就是object.proptype,这种一级一级的关系链构成了原型链。
实例.__prop__ === 原型
构造函数.proptype === 原型
实例.constructor === 构造函数
举例说明js的继承
function father(){
this.fname = 'sang'
}
function son (){
// father.call(this)
//此方法只能够继承father构造器中的函数,并且将其存放在自己的构造器函数中
}
// son.prototype = new father()
// son.prototype.constructor = son
//此方法继承了不仅仅继承了fathher,还继承了father的原型,实例出来的对象第一层有属于自己的属性,
第二层constructor包含了构造构造函数也就是son的属性,而构造函数son的构造器就是father
/。// father.prototype.sex = 'nan'
// son.prototype = father.prototype
// son.prototype.constructor = son
// console.log(son1.sex)
//此方法是直接继承father构造器原型上的属性,不会去继承构造函数的属性
// 还有浅拷贝继承和中介继承方法
var son1 = new son()
console.log(son1.fname)
es5/es6继承除了写法有什么不同
1.function定义的构造函数会提升,并且会赋予数值,class不会
2.class内部是严格模式。
3.class是没有原型对象的,也没有构造函数。
4.class只能用new来调用
5.无法重写内部类名
事件循环
对事件循环的理解
在执行代码的时候会有同步代码和异步代码两种,在执行同步代码的时候是放在主线程中执行的,异步的代码时放在任务队列中的,当同步代码在主线程执行时会形成执行栈,而任务中心的异步任务会在主线程的同步任务执行完毕之后返回给主线程一个回调,之后主线程再返回异步任务的结果,之后再去任务队列中寻找有没有任务,这个过程就叫事件循环。
微任务和宏任务的区别
js引擎在执行代码的时候会先从微任务队列中取出执行,之后再去宏任务队列取任务执行。
异步编程
异步解决方案有哪些
- 回调函数
- 订阅者模式:类似一对多的一种模式,所有订阅者对象会监听某一个主题对象,然后当主题对象发生变化的时候会通知所有的订阅者来改变他们的状态。
- promise
- 生成器,迭代器:Generator函数
- async,await
Promise的介绍以及用法
promise对象有三种状态:
1.pending:初始状态,不是成功也不是失败
2.fulfilled:成功状态
3.rejected:失败状态
promise的状态一旦确定了之后就无法改变了;
promise的方法:
then:链式调用
catch:捕捉错误
all:接受一个数组作为参数,数组中必须都是promise的实例对象,整体的promise对象的状态由参数决定,当所有参数的peomise实例对象都是成功状态的时候,整体的promise对象才是成功状态,如果有一个是失败状态,贼进入失败状态,当出现第一个失败状态时,就会传给整体的promise。
race:与all相同接受多个promise实例对象,但是与all不同的是,当率先改变状态的实例改变状态之后就会将这个状态传给整体的promise
resolve:将其变为成功状态的promise对象
reject:将其变成失败状态的promise对象
ES6数组常用方法区别
map():是指通过制定函数改变数组,并且返回数组。
find():返回数组中第一个符合相应条件的元素。
findIndex():返回数组中第一个符合相应条件的元素的位置。
filter():返回数组中所有符合条件的元素。
forEach():遍历所有数组,并且对数组中的元素做出改变,不会返回新数组。
some():查找数组中的元素,如果有相应条件的话返回true。
every():查找数组中的所有元素,当所有元素符合条件时才会返回true。
reduce():从左到右累加,并且会返回一个值。
async和await
async函数可以看做一个promise对象,当出现return时可以看作是成功状态返回的值。
await只能出现在async函数中,当await后面是一个promise对象时,会等待其正式处理完成并且返回成功结果,如果不是一个promise对象时,会将他转换成一个已正常处理的promise对象,当promise出现错误状态时,await会将其错误抛出;
async函数和promise的区别
promise是ES6的提案,async是ES7的提案。
async是不能用于回调函数,promise可以。
async使异步函数变得更像是同步函数。
当出现多个中间值的时候使用async能让语句变得更加的简洁,不需要调用多层的链式调用。