1. 数据类型
- number
- string
- boolean
- symbol
- null
- undefined
- object
2. string方法
- string.substr
string.substr(start,length) // 若length不写则延续到最后
- string.substring
string.substring(start,end) // 哪个小就把哪个看作start
2. promise怎么用
- 生成promise
function(){
return new Promise(function(resolve,reject){
if(成功){
resolve()
}else{
reject()
}
})
}
- then
$.ajax(...).then(成功函数,失败函数)
- then是链式的
$.ajax(...).then(成功函数1,失败函数1).then(成功函数2,失败函数2)
//ajax返回404,失败函数1执行,成功函数2执行
3. 手写ajax
let request = new XMLHttpRequest();
request.open('POST','/xxx');
request.onreadystatechange = ()=>{
if(request.readyState === 4 && request.status === 200){
var value = JSON.parse(request.responseText);
}
}
// 是post才用在send里写东西,不然可以直接send()
request.send('a=1&b=2');
4. 手写闭包
function createAdder(){
let n=1;
return function(){
n+=1;
console.log('n', n)
}
}
let adder = createAdder();
adder() //n===2
adder() //n===3
console.log(n) //n is not defined
5. this是什么
- fn()里面的this正常模式下是Window
- a.b.c.fn()里面的this就是a.b.c
- new F()里面的this就是F()对象
- () => {console.log(this)}里面的this就是外面的this
6. 立即执行函数
!function(){}()
作用是创造一个函数作用域,防止污染全局变量
es6新语法可以代替立即执行函数
{
let name = 'p' //用let声明变量即可
}
7. async/await语法
async init() {
this.loading = true
const { getImgTaskNumber, getCountByStatus } = this.$api.task
const promises = []
for (const index in this.imageData) {
const promise = getImgTaskNumber(this.imageData[index].name)
promises.push(promise)
const info = await promise
this.imageData[index]['taskCounts'] = info.count
this.imageData[index]['time'] = info.overdue
}
let promise = getCountByStatus('unallocated')
promises.push(promise)
this.imgDetected = await promise
promise = getCountByStatus('labeling')
this.labeling = await promise
promises.push(promise)
await Promise.all(promises)
this.loading = false
}
8. 深拷贝
- 用JSON深拷贝
let a = {...}
let b = JSON.parse(JSON.stringify(a))
但这个方法不支持函数、引用、undefined、正则...
- 递归拷贝
let china = {
nation : '中国',
birthplaces:['北京','上海','广州'],
skincolor :'yellow',
friends:['sk','ls']
}
//深复制,要想达到深复制就需要用递归
function deepCopy(o, c){
let copy = c || {}
for(let i in o){
if(typeof o[i] === 'object'){ //要考虑深复制问题了
if(o[i].constructor === Array){
//这是数组
copy[i] =[]
}else{
//这是对象
copy[i] = {}
}
deepCopy(o[i],copy[i])
}else{
copy[i] = o[i]
}
}
return copy
}
let result = {name:'result'}
result = deepCopy(china,result)
console.dir(result)
9. 数组去重
-
ES5(计数排序的逻辑)
function distinct(a) { let obj = {} let result = [] a.forEach(value => { if (!obj[value]) { obj[value] = 1 result.push(value) } }) return result } let a = [1,1,1,1,2,3,4,5,6,5,3,2,4,56,56,4,1,2,7] let b = distinct(a) console.log(b)
-
ES6
function distinct2(array){ return Array.from(new Set(array)); } distinct2([1,1,2,3]) //[1,2,3]
10. 用正则实现string.trim()
function trim(string){
return string.replace(/^\s+|\s+$/g,'')
//^\s+表示开头有一个或多个空格,|表示或,\s+$表示结尾
}
11. 什么是原型
数组的push方法就是原型里的,数组是个对象,每个对象都有一个隐藏属性__proto__
,而数组的'proto'指向数组的原型Array.prototype
,push方法就存在这里面可以直接引用(还有pop,slice,splice也是)
12. class(类)
- 类的声明不会提升
- 举例
class Rectangle {
// constructor
constructor(height, width) {
this.height = height;
this.width = width;
}
// Getter
get area() {
return this.calcArea()
}
// Method
calcArea() {
return this.height * this.width;
}
}
const square = new Rectangle(10, 10);
console.log(square.area);
// 100
- extends(继承)
class Animal {
constructor(name) {
this.name = name;
}
speak1() {
console.log(this.name + ' makes a noise.');
}
}
class Dog extends Animal {
constructor(name, gender) {
super(name)
this.gender = gender
}
speak2() {
console.log(this.name + ' barks. ' + this.gender);
}
}
var d = new Dog('Mitzie', 'man');
d.speak2();
13. JS如何实现继承
- extends(ES6)
上面的extends - 原型链(ES5)
function Animal(){
this.body = '肉体' //自身属性
}
Animal.prototype.move = function(){}
function Human(name){
Animal.apply(this,arguments) //继承Animal的自身属性
this.name = name
}
Human.prototype.__proto__ = Animal.prototype
Human.prototype.useTools = function(){}
//Human自己的原型属性
14. 实现一个延时的同步函数
function execTime(t){
let start = Date.now();
//let start = new Date().getTime()
//let start = + new Date();
while(Date.now() - start < t){}
}
console.log(1)
execTime(3000)
console.log(2)
15. 实现异步函数
function execTime(t,callback){
setTimeout(callback,t)
}
console.log(1)
execTime(3000,function(){
console.log(3)
})
console.log(2)
16. 数组方法的使用
<h1>我要学 <span class="text">__</span></h1>
<ul class="box">
<li>Java<input type="checkbox" value="Java"></li>
<li>前端<input type="checkbox" value="前端"></li>
<li>PHP<input type="checkbox" value="PHP"></li>
</ul>
<div>
<input type="text" class="ipt"><button class="add">添加</button>
</div>
let box = document.querySelector('.box')
let text = document.querySelector('.text')
let addBtn = document.querySelector('.add')
let input = document.querySelector('.ipt')
box.onclick = function (){
text.innerText = [...box.querySelectorAll('input')].filter(checkbox=>checkbox.checked)
.map(checkbox=>checkbox.value)
.join(',')
}
addBtn.onclick = function () {
let node = document.createElement('li')
let checkbox = document.createElement('input')
node.innerText = input.value
checkbox.type = 'checkbox'
checkbox.value = input.value
node.appendChild(checkbox)
box.appendChild(node)
}
17. 阻止事件冒泡
<h1>你选择的是 <span class="text"></span></h1>
<button class="btn">点我</button>
<ul class="box">
<li>菜单一</li>
<li>菜单二</li>
<li>菜单三</li>
</ul>
let box = document.querySelector('.box')
let text = document.querySelector('.text')
let button = document.querySelector('.btn')
let input = document.querySelector('.ipt')
button.onclick = function (e) {
box.style.display = 'block'
e.stopPropagation()
}
document.onclick = function () {
box.style.display = 'none'
}
box.onclick = function (e) {
e.stopPropagation()
text.innerText = e.target.innerText
}
18. 面试题,按属性分组
一个数组里有很多项(对象),每一项都有label属性,把所有label相同的项分为一个数组
function x(arr){
let t = {}
for(let i=0;i<arr.length;i++){
if(t[arr[i].label]){
t[arr[i].label].push(arr[i])
}else{
t[arr[i].label] = []
t[arr[i].label].push(arr[i])
}
}
return t
}
19. Array.sort面试题
排序
let l=[2,3,1]
l.sort() //[1,2,3]
let a = [{age:3},{age:1},{age:2}]
a.sort(function(x,y){
return x.age-y.age
})
20. Array.reduce
let a = [1,2,3]
a.reduce(function(sum,n){
return sum+n //6
},0)
第一个参数是一个函数,第二个参数是初始值传给sum,会遍历这个数组,n就是数组里的每一项,sum就是上一次return的数据
- 面试题
将一个数组里的所有小数组合并成一个大数组
let a = [[1,2,3],[4,5,6]]
a.reduce(function(sum,n){
n.forEach(function(value,key){
sum.push(value)
})
return sum
},[])
21. replace
let s = 'ad{{ra}}ds{{rd}}d'
function replaceTemp(s,object){
for(let x in object){
s = s.replace('{{'+x+'}}',object[x])
}
return s
}
replaceTemp(s,{ra:11, rd:12})
22. blur、focus事件不能冒泡
23. 判断是不是数组
a instanceof Array
Array.isArray(a)
24. 将伪数组转化为数组
let a = {0:'a',1:'b',length:2}
let b = Array.from(a)
//或者Array.prototype.slice.call(a)
25. 鼠标滑过出现浮层
onmouseover
然后display: block
,滑的快慢可以设置setTimeout
,用e.offsetTop
可以检测元素距离顶部的位置
26. 面经
27. 函数面试题
- 满足fn() === fn/fn.fn === fn
function fn(){
fn.fn=fn;
return fn
}
- 满足obj.obj.obj...... === obj
obj = {}
obj.obj = obj
obj.obj.obj.obj.obj === obj //true
27. 数组API
- 面试题一
let students = [
{name:'1',score:86},
{name:'2',score:86},
{name:'3',score:86},
{name:'4',score:86},
]
用数组API计算总分、平均分、最高分、最低分
//总分
students.map(s=>s.score).reduce((s,n)=>s+n,0)
//平均分
students.map(s=>s.score).reduce((s,n)=>s+n,0)/students.length
//最高分
students.map(s=>s.score).sort()[student.length-1]
//最低分
students.map(s=>s.score).sort()[0]
- 面试题二(sort)
用sort对学生的姓名按字典序排序
let students = [{name: 'c'},{name: 'b'},{name: 'a'}]
stundents.sort((x,y)=>{
if(x.name < y.name) {
return -1
}
if(x.name > y.name) {
return 1
}
return 0
})
28. Object面试题
- 面试题1
let obj ={a:1,b:2,c:3}
//实现select函数,select(obj, ['a', 'c'])
//输出 {a: 1, c: 3}
function select(obj,arr) {
let n = {}
arr.forEach(function(value){
n[value] = obj[value]
})
return n
}
function select2(obj,arr) {
let a = arr.reduce((o,n)=>{
o[n]=obj[n]
return o
},{})
return a
}
function select3(obj, arr) {
return arr.reduce((ret, key) =>
Object.assign(ret, { [key]: obj[key] }), {})
}
select(obj, ['a', 'c'])
//输出 {a: 1, c: 3}
- 面试题2
let p1 = {
'姓名': 'jirengu',
'性别': '男',
'年纪': 4,
}
写一个函数,实现把p1变成
<dl><dt>姓名</dt><dd>jirengu</dd><dt>性别</dt><dd>男</dd><dt>年纪</dt><dd>4</dd></dl>
- 方法一
function renderTpl(p) {
let html = '<dl>'
for(let key in p){
html += '<dt>' + key + '</dt>' + '<dd>'+ p[key] +'</dd>'
}
html += '</dl>'
return html
}
- 方法二(Object.keys)
function renderTpl(p){
return '<dl>'+ Object.keys(p).reduce((html,key)=>`${html}<dt>${key}</dt><dd>${p[key]}</dd>`,'') +'</dl>'
}
- 方法三(Object.entries)
function renderTpl(p){
return '<dl>'+ Object.entries(p).reduce((html,key)=>`${html}<dt>${key[0]}</dt><dd>${key[1]}</dd>`,'') +'</dl>'
}
- 面试题3
- 有学生列表,label代表每个学生的特点,假设每个学生的特点是唯一的,写一个函数将学生按特点分类
let sundents = [{name: 'a', label: 'happy'}, {name: 'b', label: 'angry'}]
function mapper(students){
let object = {}
students.forEach(value=>{
object[value.label] = value
})
return object
}
- 若学生的特点不是唯一,写函数将学生按特点分组
function mapped2(students) {
let object = {}
students.forEach((value)=>{
if(!object[value.label]){
object[value.label] = []
}
object[value.label].push(value)
})
return object
}
- 面试题4
写一个函数,可以判断两个对象的值是否相等
function isObjectValueEqual(a, b) {
var aProps = Object.getOwnPropertyNames(a);
var bProps = Object.getOwnPropertyNames(b);
if (aProps.length != bProps.length) {
return false;
}
for (var i = 0; i < aProps.length; i++) {
var propName = aProps[i];
if (a[propName] !== b[propName]) {
return false;
}
}
return true;
}
29. 写函数去掉开头的'$$'
let a = {$$x: 1, y: 2, z: [{$$a: 3. b: 4}]}
//把a转为json"{"a":1,"b":2,"c":3}"
//判断开头的方法
str.substring(0,2) === '$$'
//函数,这个方法牛逼
const toJson = obj => {
return JSON.stringify(obj, (key, n) => {
if(key.substring(0,2) !== '$$'){
return n
}
})
}
// n第一次是obj,接下来就是上一次return的东西,,然后这个函数会遍历上一次return的东西
30. 正则面试题
用正则匹配以135或136或137开头的11位手机号码
/^13[567]\d{8}$/
31. 写出输出的内容
for(var i=0;i<5;i++){
setTimeout(function(){
console.log(1,i)
if(i===5){
i++
}
},0)
}
var n=0
for(var m=0;m<10000000;m++){
n+=m
}
console.log(2,i)
// 2 5
// 1 5
// 1 6
// 1 6
// 1 6
// 1 6