记一次面试

183 阅读12分钟

投简历,赶面试

1.接触前端多久了

自己觉得接触前端很长时间了,但是仔细想想,答之有愧啊,虽然接触时间长,但是没能好好认真学

2.js的基本数据类型

  • ES5中的基本数据类型有六种(number,string,boolean,undefined,null,object),object是复杂数据类型

  • ES6新增一种Symbol(这种类型的对象永不相等,即创建的时候传入相同的值,可以解决属性名冲突的问题,作为标记),谷歌67版本还出现了一种bigint(是指安全存储、操作大整数)

  • object包含了哪几种类型:Data,function,Array等常用的

  • js基本类型: String,Number,Boolean,null,undefined

  • 引用类型: object。里面包含function、Array、Date

3."=="和"==="的区别

  • "=="表示相等(值相等)
  • "==="表示恒等(类型和值都要相等) js在比较的时候,"=="会先做类型转换,再判断值是否相等,如果是"==="类型和值都必须相等

4. typeof和instanceof的区别

  • typeof: 用于判断数据类型,返回值为6个字符串 string、Boolean、number、function、object、undefined。 typeof在判断nullarrayobject以及函数实例(new+函数)时,得到的都是object。这使得判断这些数据类型时,得不到真正的数据类型,因此用instanceof
  • instanceof: 判断对象是谁的实例,instanceof是对象运算符

5.原型链的概念

就是利用原型让一个引用类型继承另一个引用类型的属性和方法。

  • 原型 原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先,提供一些属性和方法,可以供后代继承,原型也是对象
  • prototype 是构造函数的属性(默认),是一个空的对象
// Person.prototype.name="mm"
// Person.prototype.sex = "男"
Person.prototype = {
    name:'mm',
    sex:'男'
}
function Person(){
    this.age = 17,
    this.sex = "女"
}
var person = new Person()
console.log(person)
console.log(person.name)

父有子无取父亲,父有子有取儿子,父无子无undefined prototype可避免代码冗余,将公有部分提取出来放在原型 通过对象修改原型的属性基本不可能,可通过prototype手动修改 对象可以通过 delete obj.属性来删除属性,但是不可以删除原型的属性

  • constructor 构造器,返回构造这个对象的构造函数,可以手动更改这个对象的构造函数
console.log(person.constructor) //返回Person这个构造函数
function Car(){}
Car.prototype.constructor = Person
var car = new Car()
console.log(car.constructor)   // 手动更改,返回Person
  • __proto__ 对象查看原型,__proto__里面放的是原型
  • 原型链
Grand.prototype.lastname="yyy"
function Grand(){this.age = 12}
var grand = new Grand()
Father.prototype = grand
function Father(){this.sex = "女"}
var father = new Father()
Son.prototype = father
function Son(){this.car = 'w'}
var son =new Son()
console.log(son)
console.log(son.car)
console.log(son.sex)
console.log(son.name)
console.log(son.__proto__ == Son.prototype)
console.log(son.__proto__.__proto__ == Father.prototype)
console.log(son.__proto__.__proto__.__proto__ == Grand.prototype)

就近原则,原型链的终止端是Object.prototype 子可以改变父的引用值(堆),不可以修改原始值

6.闭包的原理

闭包: 闭包让你可以在一个内层函数中访问到其外层函数的作用域。当内部函数保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏

function test(){
     var a = 100
     function test1() {
         console.log(a)
     }
     return test1
 }
 var out = test() // test1脱离test的影响,将test1保存到全局
 out()
 
 // 不用return
 var demo
 function test(){
    var a = 100
    function test1() {
        console.log(a)
    }
    demo = test1
}
test()
demo()

7.变量提升

js代码执行过程分为两个阶段

  • 1.词法分析(主要包括分析变量声明、分析函数声明、分析形参)
  • 2.执行阶段 变量提升
    var a = 100;
    console.log(a,b)
    var b = 200
    // 结果是 100 undefined

函数提升

具名函数的声明有两种方式:

    1. 函数声明式
    1. 函数字面量式
// 函数声明式
function bar(){}
// 函数字面量式
var foo = function(){}

函数声明式的提升现象和变量提升略有不同,函数声明式会提升到作用域最前边,并且将声明内容一起提升到最上边。 函数字面量式声明 和普通变量一样 提升的 只是一个没有值的变量。

bar()  // 100
function bar(){
	console.log(100)
}
//
bar()  // 报错:TypeError: bar is not a function
var bar = function(){
  console.log(100)
}
  • 在ES6中,let、const不存在变量提升,只有var存在变量提升
  • 所有的声明都会提升到作用域的最顶上去。
  • 同一个变量只会声明一次,其他的会被忽略掉或者覆盖掉。
  • 函数声明的优先级高于变量声明的优先级,并且函数声明和函数定义的部分一起被提升。

8.什么是解构赋值

es6允许按照一定的模式,从数组对象中提取值,称为解构赋值 特点

  • 1.给变量赋值
  • 2.值的来源是对象或数组
  • 3.规则:按一定的模式 一般用在数据交互、ajax请求数据
//1. 数组解构
let [a,b,c] = [1,2,3];
console.log(a,b,c)
// 相当于
let arr = [1,2,3];
console.log(arr[0],arr[1],arr[2])
//2.对象解构
let json = {
  name:'ymm',
  age:18,
  job:'web'
}
let {name,age,job} = json;
console.log(name,age,job) // ymm 18 web
// 3.起别名
let person = {
  name:'ymm',
  age:18,
  job:'web'
  }
let {name:n,age:a,job:j} = person;
console.log(n,a,j)
// 俩个obj的属性有一样的,如何解构
let obj1 = {
  data:1,
  name:'ymm'
  }
 let obj2 = {
  data:1,
  age:16
  }
let {data:B1d,name} = obj1;
let {data:B2d,age} = obj2;
console.log(B1d,B2d,name,age)

// undefined和null
let [a,b,c,d] = [1,,3,null]
console.log(a,b,c,d) // 1 undefined 3 null
let [e,f="暂无",g] = [1,,null]
console.log(e,f,g == null?'这是null':g)
// 4.交换两个数的位置
let [a,b] = [10,5];
    [b,a] = [a,b];
console.log(a,b)
// 5.接收函数的返回值
function fun(){
	// 函数体
   return {
     left:20,
     tops:30
  }
}
let {left,tos} = fun()
console.log(left,tops)

在js的顶层有一个全局对象window,凡是window上的属性和方法就是全局的属性和方法,name和top属性已被window对象使用

9.Promise对象的作用

代表未来将要发生的事件,用来传递异步操作的消息

特点

  • 1.对象的状态不受外界的影响。Promise代表一个异步操作有三种状态 pending:初始状态,不是成功或者失败 fulfilled:操作成功状态 rejected:操作失败状态 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操做都无法更新这个状态
  • 2.一旦状态发生改变就不会再变,任何时候都可以得到这个结果 优缺点
  • 优点: (1)将异步任务同步表达出来,避免了层层嵌套的回调函数;(2)Promise对象提供统一的接口,使得控制异步操作更加容易
  • 缺点: (1)无法取消Promise,一旦新建就会立即执行,无法中途取消;(2)如果不设置回调函数,Promise内部抛出错误不会反应到外部;(3)当处于pending状态时,无法得知目前进展到哪一阶段(刚刚开始还是即将完成)

Pomise的创建(由Promise构造器进行实例化)

var promise = new Promise(function(resolve,reject){
    // 异步处理
    // 处理结束后调用resolve或者reject
})

Promise构造函数包含一个参数和一个带有resolve(解析)和reject(拒绝)的两个参数的回调,如果一切正常调用resolve,反之调用reject

Promise.then().catch():对于已经实例化过的Promise对象 可以调用 Promise.all():用于多个Promise实例,包装成一个新的Promise实例 Promise.race():将多个Promise实例包装成一个新的promise实例 Promise.resolve():将现有对象转为Promise对象 Promise.reject():会返回一个新的Promise实例,该状态位rejected

10.js如何添加一个事件监听

1.直接添加(直接绑定事件)

 ele.onclick = function(){}

这种方法兼容主流的浏览器,但在绑定多个事件时,只有最后一个事件会被触发

ele.onclick = handler1;
ele.onclick = handler2;
ele.onclick = handler3;
// 只有hander3会被触发

2.addEventListener和attachEvent

事件冒泡和事件捕获

  • 事件冒泡由最里面向最外层触发
  • 事件捕获由最外层向最里层触发
<div id="div1">
  <div id="div2">
    <div id="div3">
    	点击我
    </div>
  </div>
</div>

冒泡事件流传播顺序:div3->div2->div1->body->html->document 捕获事件流传播顺序:document->html->body->div1->div2->div3

addEventListener: 标准

ele.addEventListener("click",handler1,false);
ele.addEventListener("click",handler2,false);
ele.addEventListener("click",handler3,false);

执行顺序是1-2-3(handler1,handler2,handler3),最先添加的事件先执行 addEventListener()有三个参数,参数一是事件名(必填),参数二是事件的执行函数(必填),参数三是参数是冒泡获取,是一个布尔值:当为false(默认)时表示由里向外(冒泡),true时表示由外向里(捕获)

removeEventListener()是删除事件处理程序,也收受三个参数:要处理的事件名、作为事件处理程序的函数、一个布尔值(如果这个布尔值参数是true,在捕获阶段调用,如果这个参数是false,在冒泡阶段调用)

一起使用时,参数要一致(不可直接传入相同的函数) attachEvent: IE

ele.attach("click",handler1);
ele.attach("click",handler2);
ele.attach("click",handler3);

三个方法的执行顺序是3-2-1(handler3,handler2,handler1),最后添加的事件先执行 attach()接受两个参数,事件名和事件处理函数(IE8及更早版本只支持冒泡事件) deattach()接受两个参数,事件名和事件处理函数

一起使用时,参数要一致(不可直接传入相同函数的额函数名)

11.内存泄漏

什么是内存泄漏: 是指程序中己动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果,简答来讲就是由于疏忽或错误导致程序未能释放已经不再使用的内存,从而造成内存的浪费。

内存泄漏的场景

  • 闭包
  • 意外的全局变量(一个未声明变量的使用,会在全局对象中创建一个新的变量)--- 在js文件添加 'use strict',开启严格模式可解决该问题
function fun(){
  this.a = "test"
}
fun()
// a应该是fun内部作用域变量的引用,a未声明就赋值,因此会在全局声明一个a
  • 计时器和回调函数timers 定时器setInterval或者setTimeout在不需要使用的时候,没有被clear,导致定时器的回调函数及其内部依赖的变量都不能被回收,这就存在内存泄漏。

    解决方式:当不需要interval或者timeout的时候,调用clearInterval或者clearTimeout

  • DOM泄漏

  • console(console.log的对象不能被垃圾回收)

12.跨域的解决方式

跨域的原因

由于浏览器的同源策略限制。所谓同源就是在同一个域中,两个页面的协议、域名、端口号都保持一致。

什么是跨域 当一个url的协议、域名、端口号三者有一项不同就是跨域

跨域的解决方法

  • 设置doucument.domain()
  • 跨文档通信API:window.postMessage()
  • JSONP
  • CORS

blog.csdn.net/qq_38128179…

13.ES6中的装饰器

装饰器(Decorator)是一种与类(class)相关的语法,用来注释或修改类和类的方法。 装饰器是一种函数,写成@ + 函数名。它可以放在类和类方法的定义前面

@testable
class myClass{
  // ...
}
function teatable(target){
	target.isTestable = true;
}
myClass.isTestable // true

@testable就是一个装饰器,修改了myClass这个类的行为,并为它加上了静态属性isTestabletestable函数的参数target是myClass类本身

14.观察者模式如何写

什么是观察者模式(目标对象、观察者对象) 观察者模式是软件设计模式的一种,一个目标对象管理所有相依于它的观察者对象,并且在它本身的状态发生改变时主动发出通知。(数据发生改变时对应的处理函数自动执行)

在Vuejs中相当于v-model值改变时,watch进行监听

blog.csdn.net/lm278858445…

什么是发布者/订阅模式(订阅者、调度中心、发布者) 订阅者把自己想订阅的事件注册到调度中心,当该事件触发的时候,发布者发布该事件到调度中心(顺带上下文),由调度中心统一调度订阅者到调度中心的处理代理。

segmentfault.com/a/119000001…

15.webpack如何搭建开源项目

blog.csdn.net/cdnight/art…

现在的项目一般都在内部集成

16.常用的git命令

1.git  config --global user.name " "
2.git  config --global user.email " "
3.git init  初始化,把目录变成git可管理的仓库
4.git add 把文件添加到版本库
(1)git add + 文件名.类型   单个文件添加
(2)git add ./    全部文件添加
(3)git add .\src\ 某个文件夹下的文件提交
5.git commit -m ‘版本说明(描述)’  把文件提交到仓库(提交到本机服务器)
6.git push (联网)
7.git status 查看状态(可以让我们掌握仓库当前的状态)
8.git diff 查看difference,显示的格式正是Unix通用的diff格式
9.git log  查看日志
如果嫌git log查看出来的日志太长太麻烦的话可以写成
git log  --pretty=oneline   
(看到的一大串类似1094adb...的是commit id(版本号))
10.git reset --hard head^  版本回退
Git reset ---hard 版本号    回退到指定版本
11.git reflog 版本还原
12.git stash   用于于临时保存和回复修改,保存当前工作进度,将工作区和暂存区恢复到修改之前。
13.git stash pop 恢复工作进度到工作区
14.git checkout  -b name 创建分支
15.git branch 查看当前分支
16.git checkout name 切回分支
17.git merge name 合并分支
18.git branch -d name 删除分支
19.Git branch -D name
本地库跟远程库交互:(联网)
git clone  + url :克隆远程库
  功能:①完整的克隆远程库为本地库,②为本地库新建origin别名,③初始化本地库
git remote -v:查看远程库地址别名
git remote rm + name:删除本地中远程库别名
git push:本地库某个分支推送到远程库,分支必须指定
git pull :把远程库的修改拉取到本地(该命令包括git fetch,git merge)
git fetch :抓取远程库的指定分支到本地,但没有合并
git merge :将抓取下来的远程的分支,跟当前所在分支进行合并

17.vuex的作用?有那些核心的概念

vuex专门为vuejs应用程序管理开发的状态管理模式