this.find = function(item){ //查找
var currNode = this.head;
while(currNode.element != item){
if(currNode.next === this.head) return null;
currNode = currNode.next;
};
return currNode;
};
this.insert = function(newElement, item){ //在item之后插入
var newNode = new Node(newElement);
var current = this.find(item);
newNode.next = current.next;
current.next = newNode;
};
this.display = function(){ //输出列表
var currNode = this.head;
while(currNode.next !== this.head){
console.log(currNode.next.element);
currNode = currNode.next;
}
};
this.remove = function(element){ //删除
var currNode = this.head;
while(1){
if(currNode.next == this.head) return false;
if(currNode.next.element == element) break;
currNode = currNode.next;
}
currNode.next = currNode.next.next;
};
}
双向链表
function Node(element){
this.element = element;
this.next = null;
this.previous = null;
}
function LList(){
this.head = new Node(“head”);
this.tail = this.head;
this.find = function(item){ //查找
var currNode = this.head;
while(currNode.element != item){
if(currNode.next === null) return null;
currNode = currNode.next;
};
return currNode;
};
this.insert = function(newElement, item){ //在item之后插入
var newNode = new Node(newElement);
var current = this.find(item);
newNode.next = current.next;
current.next = newNode;
current.next.previous = newNode;
newNode.previous = current;
};
this.display = function(){ //输出列表
var currNode = this.head;
while(currNode.next !== null){
console.log(currNode.next.element);
currNode = currNode.next;
}
};
this.remove = function(item){ //删除
var currNode = this.find(item);
if(currNode){
currNode.previous.next = currNode.next;
currNode.next.previous = currNode.previous;
currNode.next = null;
currNode.previous = null;
return true;
}
return false;
};
this.dispReverse = function(){ //反向输出
var currNode = this.tail;
while(currNode.previous !== null){
console.log(currNode.element);
currNode = currNode.previous;
}
};
}
字典
function dictionary(){
this.dataStore = [];
this.add = function(key, value){ //插入
if(this.find(key)) console.log(“'” + key + “’ exists”);
else this.dataStore[key] = value;
};
this.find = function(key){ //查找
return this.dataStore[key];
};
this.remove = function(key){ //删除
delete this.dataStore[key];
};
this.showAll = function(){ //有序输出
var keys = Object.keys(this.dataStore).sort();
keys.forEach(function(key){
console.log(key + " -> " + this.dataStore[key]);
});
};
this.count = function(){ //计数
return Object.keys(this.dataStore).length;
};
this.clear = function(){ //清除
for(var k in this.dataStore){
if(dataStore.hasOwnPorperty(k)){
delete this.dataStore[k];
}
}
};
}
集合
function Set(){
if(arr){
this.arr = arr.filter(function(item, index) {
return arr.indexOf(item) === index;
});
} else {
this.arr = [];
}
}
Set.prototype.constructor = Set;
Myset.prototype.sort = function(fun){ //排序
this.arr.sort(fun);
return this;
};
Set.prototype.add = function(data){ //添加
if(this.dataStore.indexOf(data) < 0){
this.dataStore.push(data);
}
return this;
};
Set.prototype.show = function(){ //输出
console.log(this.dataStore.join(“,”));
return this;
};
Set.prototype.remove = function(data){ //删除
var pos = this.dataStore.indexOf(data);
if(pos > -1){
this.dataStore.splice(pos, 1);
}
return this;
};
Set.prototype.size = function(){ //得到当前集合大小(元素数量)
return this.dataStore.length;
};
Set.prototype.contains = function(data) { //是否包含data
return this.dataStore.indexOf(data) > -1;
};
Set.prototype.clone = function(){ //复制当前集合
var tempSet = new Set();
for(var i = 0; i < this.size(); ++i)
tempSet.add(this.dataStore[i]);
return tempSet;
};
Set.prototype.union = function(set){ //求并集
var tempSet = this.clone();
for(var i = 0; i < set.size(); ++i){
if(!tempSet.contains(set.dataStore[i]))
temp.dataStore.push(set.dataStore[i]);
}
return tempSet;
};
Set.prototype.interSect = function(set){ //求交集
var tempSet = new Set();
for(var i = 0; i < this.size(); ++i){
if(set.contains(this.dataStore[i]))
tempSet.add(this.dataStore[i]);
}
return tempSet;
};
Set.prototype.subSet = function(set){ //判断当前集合是否set的子集
if(this.size() > set.size()) return false;
else{
for(var i = 0; i < this.size(); ++i){
if(!set.contains(this.dataStore[i]))
return false;
}
}
return true;
};
this.difference = function(set){ //求差集 this-set
var tempSet = new Set();
for(var i = 0; i < this.dataStore.length; ++i){
if(!set.contains(this.dataStore[i]))
tempSet.add(this.dataStore[i]);
}
return tempSet;
};
哈希表
function HashTable(){
this.table = [];
//this.values = [];
//当key是整数的时候可以简单的使用simpleHash
this.simpleHash = function(data){ //这个函数下文不会用到
var total = 0;
for(var i = 0; i < data.length; ++i)
total += data.charDodeAt(i);
return total % this.table.length;
};
//simpleHash()有一个严重的问题:不同字符串可能得到相同hash码,比如"Raymond"和"Clayton"。 这叫做哈希碰撞(hashing collision)
this.betterHash = function(string, arr){
const H = 31; //引入一个质数
var total = 0;
for(var i = 0; i < string.length; ++i)
total += H * total + string.charCodeAt(i);
total = total % arr.length;
return parseInt(total);
};
this.showDistro = function(){
var n = 0;
for(var i = 0; i < this.table.length; ++i){
// if(this.table[i] !== undefined) //线性探针法使用这个if
if(this.table[i][0] !== undefined) //散列法使用这个if
console.log(i + ": " + this.table[i]);
}
};
//即使使用了betterHash,也不能保证在所有输入中不会一重复的输出,因此产生了散列法(separate chaining)和线性探针法(linear probing)
//建立散列
this.buildChains = function(){
for(var i = 0; i < this.table.length; ++i)
this.table[i] = [];
};
//散列法对应put函数
this.put = function(data){
var pos = this.betterHash(data);
var index = 0;
if(this.table[pos][index] === undefined)
this.table[pos][index] = data;
else {
while(this.table[pos][index] !== undefined) ++index;
this.table[pos][index] = data;
}
};
//散列法对应get函数
this.get = function(key){
var pos = this.betterHash(key);
var index = 0;
if(this.table[pos][index] === key)
return this.table[pos][index + 1];
else {
while(this.table[pos][index] !== key) index += 2;
return this.table[pos][index + 1];
}
return undefined;
};
/*
//线性探针法对应put函数
this.put = function(key, data){
var pos = this.betterHash(data);
if(this.table[pos] == undefined){
this.table[pos] = key;
this.values[pos] = data;
} else {
while(this.table[pos] != undefined) ++pos;
this.table[pos] = key;
this.values[pos] = data;
}
};
//线性探针法对应get函数
this.get = function(key){
var hash = -1;
hash = this.betterHash(key);
if(hash > -1){
for(var i = hash; this.table[hash] != undefined; ++i){
if(this.table[hash] == key)
return this.values[hash];
}
}
};
*/
}
树
function Node(data, left, right){ //树节点
this.data = data;
this.left = left;
this.right = right;
this.show = function(){ return this.data; };
}
//建立一个二叉查找树(Binary Search Tree)
function BST(){
this.root = null;
this.insert = function(data){
var n = new Node(data, null, null);
if(this.root === null) {
this.root = n;
}
else{
var current = this.root;
var parent;
while(true){
parent = current;
if(data < current.data){
current = current.left;
if(current === null){
parent.left = n;
break;
}
}
else{
current = current.right;
if(current == null){
parent.right = n;
break;
}
}
}
}
};
//中序遍历
this.inOrder = function(node){
if(node !== null){
inOrder(node.left);
console.log(node.show() + " ");
inOrder(node.right);
}
};
//前序遍历
this.preOrder = function(node){
if(node !== null){
console.log(node.show() + " ");
preOrder(node.left);
preOrder(node.right);
}
};
//后序遍历
this.postOrder = function(node){
if(node !== null){
postOrder(node.left);
postOrder(node.right);
console.log(node.show() + " ");
}
};
//得最小值
this.getMin = function(){
var current = this.root;
while(current.left !== null)
current = current.left;
return current.data;
};
//得最大值
this.getMax = function(){
var current = this.root;
while(current.right !== null)
current = current.right;
return current.data;
};
//查找值
function find(data){
var current = this.root;
while(current !== null){
if(current.data == data) return current;
else if(data < current.data) current = current.left;
else if(data > current.data) current = current.right;
}
return null;
};
//删除值
this.removeData = function(data){
this.root = removeNode(this.root, data);
function removeNode(node, data){
if(node === null) return null;
if(data === node.data){
if(node.left == null && node.right == null) return null;
if(node.left == null) return node.right;
if(node.right == null) return node.left;
var tempNode = getSmallest(node.right);
node.data = tempNode.data;
node.right = removeNode(node.right, tempNode.data);
return node;
}
else if(data < node.data){
node.left = removeNode(node.left, data);
return node;
} else{
node.right = removeNode(node.right, data);
return node;
}
}
};
}
图
function Graph(v_num){
this.vertices = v_num; //定点数量
this.edges = 0; //边的数量
this.adj = []; //邻接矩阵
this.marked = []; //用于遍历时标记已遍历的点
this.vertexList = []; //存放顶点
this.edgeTo = []; //在寻找最短路径时,存放轨迹
for(var i = 0; i < this.vertices; ++i){ //初始化邻接矩阵
this.adj[i] = [];
this.adj[i] = push(“”);
}
this.addEdge = function(v, w){ //添加边,传入2个点
this.adj[v].push(w);
this.adj[w].push(v);
this.edges++;
};
this.showGraph = function(){ //输出图
for(var i = 0; i < this.vertices; ++i){
console.log(i + " -> ");
for(var j = 0; j < this.vertices; ++j){
if(this.adj[i][j] !== undefined)
console.log(this.adj[i][j] + " ");
}
console.log(“\n”);
}
};
//深度优先遍历
this.dfs = function(v){
for(var i = 0; i < this.vertices; ++i) //初始化标记矩阵
this.mark[i] = false;
innerDfs(v);
function innerDfs(v){
this.marked[v] = true;
if(this.adj[v] !== undefined)
console.log(v + " ");
for(var i = 0; i < this.adj[v].length; ++i){
var ver = this.adj[v][i];
if(!this.marked[ver]) this.innerDfs(ver);
}
}
};
//广度优先遍历
this.bfs = function(s){
for(var i = 0; i < this.vertices; ++i) //初始化标记矩阵
this.mark[i] = false;
var queue = []; //存放访问过的节点
this.marked[s] = true;
queue.push(s);
while(queue.length > 0){
var v = queue.shift();
if(v !== undefined) console.log(s + “”);
for(var i = 0; i < this.adj[v].length; ++i){
var ver = this.adj[v][i];
if(!this.marked[ver]){
this.edgeTo[ver] = v;
this.marked[ver] = true;
queue.push(ver);
}
}
}
};
this.hasPathTo = function(v){ //判断是否有到节点v的路径
return this.marked[v];
};
this.showPath = function(){ //显示路径
while(paths.length > 0){
if(paths.legnth > 1) console.log(paths.pop() + ‘-’);
else console.log(paths.pop());
}
};
this.pathTo = function(v) { //计算path路径
var path = [];
var source = 0;
if(!this.hasPathTo(v))
return undefined;
for(var i = v; i !== source; i = this.edgeTo[i])
path.push(i);
ES6
-
列举常用的ES6特性:
-
箭头函数需要注意哪些地方?
-
let、const、var
-
拓展:var方式定义的变量有什么样的bug?
-
Set数据结构
-
拓展:数组去重的方法
-
箭头函数this的指向。
-
手写ES6 class继承。
微信小程序
-
简单描述一下微信小程序的相关文件类型?
-
你是怎么封装微信小程序的数据请求?
-
有哪些参数传值的方法?
-
你使用过哪些方法,来提高微信小程序的应用速度?
-
小程序和原生App哪个好?
-
简述微信小程序原理?
-
分析微信小程序的优劣势
-
怎么解决小程序的异步请求问题?
其他知识点面试
-
webpack的原理
-
webpack的loader和plugin的区别?
-
怎么使用webpack对项目进行优化?
-
防抖、节流
-
浏览器的缓存机制
-
描述一下二叉树, 并说明二叉树的几种遍历方式?
-
项目类问题
-
笔试编程题:
最后
技术栈比较搭,基本用过的东西都是一模一样的。快手终面喜欢问智力题,校招也是终面问智力题,大家要准备一下一些经典智力题。如果排列组合、概率论这些基础忘了,建议回去补一下。