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