什么是闭包?
答:闭包说的通俗一点就是可以在函数外部访问到函数内部的变量。因为正常情况下函数外部是访问不到函数内部作用域变量的,作用域分为了全局.函数级.块级作用域.
表象判断是不是闭包:函数嵌套函数,内部函数被return 内部函数调用外层函数的局部变量
优点:可以隔离作用域,不造成全局污染
缺点:由于闭包长期驻留内存,则长期这样会导致内存泄露
如何解决内存泄露:将暴露外部的闭包变量置为null
说一下JS中的原型链的理解?
答:原型链是理解JS面向对象很重要的一点,这里主要涉及到两个点,一是_ _proto_ ,二是prototype,举个例子吧,这样还好说点,例如:我用function创建一个Person类,然后用new Person创建一个对象的实例假如叫p1吧,在Person类的原型 prototype添加一个方法,例如:play方法,那对象实例p1如何查找到play这个方法呢,有一个查找过程,具体流程是这样的:首先在p1对象实例上查找是否有play方法,如果有则调用执行,如果没有则用p1.__proto__(_proto_是一个指向的作用,指向上一层的原型)往创建p1的类的原型上查找,也就是说往上查找,如果在找到play方法则执行,否则继续往上查找,则用.__proto__继续往上查找,找到,如果有play方法则执行之,否则用.__proto__继续再往上查找,但.__proto__上一级是null,也就是原型链的*,结束原型链的查找,这是我对原型链的理解
说一下JS继承(含ES6的)--或者人家这样问有两个类A和B,B怎么继承A?
答:JS继承实现方式也很多,主要分ES5和ES6继承的实现先说一下ES5是如何实现继承的ES5实现继承主要是基于prototype来实现的,具体有三种方法
一是原型链继承:即 =new A()
二是借用构造函数继承(call或者apply的方式继承)
function B(name,age) {
(this,name,age)
}
三是组合继承
组合继承是结合第一种和第二种方式
再说一下ES6是如何实现继承的
ES6继承是目前比较新,并且主流的继承方式,用class定义类,用extends继承类,用super()表示父类
说一下JS原生事件如何绑定
答:JS原生绑定事件我知道的有三种吧:
一是html事件处理程序
二是DOM0级事件处理程序
三是DOM2级事件处理程序
其中:html事件现在早已不用了,就是在html各种标签上直接添加事件,类似于css的行内样式,缺点是不好维护,因为散落在标签中,也就是耦合度太高
例如:<button οnclick=”事件处理函数”>点我</button>
第二类是DOM0级事件,目前在PC端用的还是比较多的绑定事件方式,兼容性也好,主要是先获取dom元素,然后直接给dom元素添加事件
例如:var btn=(‘id元素’)
btn.οnclick=function() {
//要处理的事件逻辑
}
DOM0事件如何移除呢?很简单:btn.οnclick=null;置为空就行
优点:兼容性好
缺点:只支持冒泡,不支持捕获
第三类是DOM2级事件,移动端用的比较多,也有很多优点,提供了专门的绑定和移除方法
例如: var btn=(‘id元素’)
//绑定事件
(‘click’,绑定的事件处理函数名,false)
//移除事件
(‘click’,要移除的事件处理函数名,false)
优点:支持给个元素绑定多个相同事件,支持冒泡和捕获事件机制
说一下JS原生常用dom操作方法?
答:js原生dom操作方法有?
查找:getElementByid,
getElementsByTagName,
querySelector,
querySelectorAll
插入:appendChild,insertBefore
删除:removeChild
克隆:cloneNode
设置和获取属性:setAttribute(“属性名”,”值”),getAttibute(“属性名”)
说一下ES6新增特性?
答:ES6新增特性常用的主要有:let/const,箭头函数,模板字符串,解构赋值,模块的导入(import)和导出(export default/export),Promise,还有一些数组字符串的新方法,其实有很多,我平时常用的就这些.
依托于你答案可能被问道的问题:
Const声明一个常量.是对象的话.能不能修改里面的值?
可以的. 因为这个常量的不能修改指的是指向的地址不能修改,我只是修改里面的内容.堆空间地址是不变,所以可以修改
箭头函数里面的this指向是什么样子的?
箭头函数和普通函数的区别是.箭头函数指向定义时.定义的时候this就确定了.指向它的外层. 普通函数是指向调用时.谁调用的我.this就指向的谁
模版字符串:${ 变量 }
解构赋值: 数组解构,函数参数解构 对象解构
JS设计模式有哪些(单例模式观察者模式等)
答:JS设计模式有很多,但我知道的有单例模式,观察者模式
单例模式:就是保证一个类只有一个实例,实现的方法一般是先判断实例存在与否,如果存在直接返回,如果不存在就创建了再返回,这就确保了一个类只有一个实例对象。在JavaScript里,单例作为一个命名空间提供者,从全局命名空间里提供一个唯一的访问点来访问该对象。
观察者模式: 观察者的使用场合就是:当一个对象的改变需要同时改变其它对象,并且它不知道具体有多少对象需要改变的时候,就应该考虑使用观察者模式。
总的来说,观察者模式所做的工作就是在解耦,让耦合的双方都依赖于抽象,而不是依赖于具体。从而使得各自的变化都不会影响到另一边的变化
说一下你对JS面向对象的理解
答:JS面向对象主要基于function来实现的,通过function来模拟类,通过prototype来实现类方法的共享,跟其他语言有着本质的不同,自从有了ES6后,把面向对象类的实现更像后端语言的实现了,通过class来定义类,通过extends来继承父类,其实ES6类的实现本质上是一个语法糖,不过对于开发简单了好多。
说一下JS数组常用方法(至少6个)
答:在开发中,数组使用频率很频繁,JS数组常用方法有:push,pop,unshift,shift,splice,join,concat,forEach,filter,map,sort,some,every,includes reduce好多,不过都是平时开发中很常用的方法,大家可以补充一点儿es6的
说一下JS数组内置遍历方法有哪些和区别
答:JS数组内置遍历(遍历就是循环的意思)方法主要有:
forEach:这个方法是为了取代for循环遍历数组的,返回值为undefined例如:
let arrInfo=[4,6,6,8,5,7,87]
((item,index,arr)=>{
//遍历逻辑
})
其中:
item代码遍历的每一项,
index:代表遍历的每项的索引,
arr代表数组本身
filter:是一个过滤遍历的方法,如果返回条件为true,则返回满足条件为true的新数组
let arrInfo=[4,16,6,8,45,7,87]
let resultArr=((item,index,arr)=>{
//例如返回数组每项值大于9的数组
return item>9
})
map:这个map方法主要对数组的复杂逻辑处理时用的多,特别是react中遍历数据,也经常用到,写法和forEach类似
some:这个some方法用于只要数组中至少存在一个满足条件的结果,返回值就为true,否则返回fasel, 写法和forEach类似
every:这个every方法用于数组中每一项都得满足条件时,才返回true,否则返回false, 写法和forEach类似
数组 的reduce方法
说一下JS作用域和作用域链
答:JS作用域也就是JS识别变量的范围,作用域链也就是JS查找变量的顺序
先说作用域,JS作用域主要包括全局作用域、局部作用域和ES6的块级作用域
全局作用域:也就是定义在window下的变量范围,在任何地方都可以访问,
局部作用域:是只在函数内部定义的变量范围
块级作用域:简单来说用let和const在任意的代码块中定义的变量都认为是块级作用域中的变量,例如在for循环中用let定义的变量,在if语句中用let定义的变量等等
注:尽量不要使用全局变量,因为容易导致全局的污染,命名冲突,对bug查找不利。
2️而所谓的作用域链就是由最内部的作用域往最外部,查找变量的过程.形成的链条就是作用域链
原型链往外层找,找到null
作用域链,从找到的地方外外层,一直找到window
说一下从输入URL到页面加载完中间发生了什么?
DOM树 构建一个样式表.组合成一颗render树,页面经过重绘(重塑)和回流的过程.
答:大致过程是这样的:
- DNS解析
- TCP连接
- 发送HTTP请求
- 服务器处理请求并返回需要的数据
- 浏览器解析渲染页面
- 连接结束
输入了一个域名,域名要通过DNS解析找到这个域名对应的服务器地址(ip),通过TCP请求链接服务,通过WEB服务器(apache)返回数据,浏览器根据返回数据构建DOM树,再把css形成一个样式表.这两个东西结合,变成了render树.页面上通过重绘和回流的过程,渲染出页面来
JS事件代理(事件委托)是什么?以及实现原理?$('ul').on('click','li',function(){})
能够给动态添加的元素绑定事件
答:JS事件代理就是通过给父级元素(例如:ul)绑定事件,不给子级元素(例如:li)绑定事件,然后当点击子级元素时,通过事件冒泡机制在其绑定的父元素上触发事件处理函数,主要目的是为了提升性能,因为我不用给每个子级元素绑定事件,只给父级元素绑定一次就好了,在原生js里面是通过event对象的target属性实现
var ul = ("ul");
= function(e){//e指event,事件对象
var target = || ; //target获取触发事件的目标(li)
if(() == 'li'){//目标(li)节点名转小写字母,不转的话是大写字母
alert()
}
}
jq方式实现相对而言简单 $(“ul”).on(“click”,“li”,function(){//事件逻辑}) 其中第二个参数指的是触发事件的具体目标,特别是给动态添加的元素绑定事件,这个特别起作用