function mySetInterval(fn, ms) {
function interval(){
setTimeout(interval, ms);
fn();
}
setTimeout(interval, ms);
}
// 更好的實現
function mySetInterval(fn, ms, count) {
function interval() {
if(typeof count === 'undefined' || count-- > 0) {
setTimeout(interval, ms);
try {
fn();
} catch(e) {
t = 0;
throw e.toString();
}
}
}
setTimeout(interval, ms);
}
複製代碼
例如:有數組[10, 22, 32, 4, 4, 5, 6, 9, 8, 8, 2],返回結果爲2
4, 4
8, 8
複製代碼
太多了,跟面試前補充的簡歷幾乎同樣javascript
根據內容的結構化(內容語義化),選擇合適的標籤(代碼語義化),
便於開發者閱讀和寫出更優雅的代碼的同時讓瀏覽器的爬蟲和機器很好地解析
複製代碼
TCP鏈接 須要通過「三次握手」
HTTP/1.0 客戶端發送的每次請求都須要服務器回送響應,在請求結束後,會主動釋放鏈接
HTTP/1.1 一次鏈接中處理多個請求,而且多個請求能夠重疊進行,不須要等待一個請求結束後再發送下一個請求
複製代碼
補充:css
第一步:
設置響應消息頭Access-Control-Allow-Credentials值爲「true」。
同時,還須要設置響應消息頭Access-Control-Allow-Origin值爲指定單一域名
第二步:
客戶端須要設置Ajax請求屬性withCredentials=true,讓Ajax請求都帶上Cookie
複製代碼
1. elementObject.addEventListener(eventName,handle,useCapture)
2. elementObject.attachEvent(eventName,handle);(僅支持IE8及如下)
3. document.getElementById("demo").onclick = function(){};
複製代碼
1. <meta name="viewport"
content="width=device-width, height=device-height, inital-scale=1.0, maximum-scale=1.0, user-scalable=no;"
/>
2. 網頁內部的元素寬度要使用百分比,在不一樣的屏幕大小下需使用媒體查詢定義不一樣的css代碼
代碼解析:
width:控制 viewport 的大小,能夠是指定的一個值,好比 1920,或者是特殊的值,如 device-width 爲設備的寬度,單位爲縮放爲 100% 時的 CSS 的像素。
height:和 width 相對應,指定高度,能夠是指定的一個值,好比 1080,或者是特殊的值,如 device-height 爲設備的高度。
initial-scale:初始縮放比例,即當頁面第一次載入是時縮放比例。
maximum-scale:容許用戶縮放到的最大比例。
minimum-scale:容許用戶縮放到的最小比例。
user-scalable:用戶是否能夠手動縮放。
複製代碼
1. IE: Trident內核
2. Firefox:Gecko內核
3. Google:Blink內核
4. Safari:Webkit內核
-webkit- ,針對safari,chrome瀏覽器的內核CSS寫法
-moz-,針對firefox瀏覽器的內核CSS寫法
-ms-,針對ie內核的CSS寫法
-o-,針對Opera內核的CSS寫法
複製代碼
CSS響應式設計適配多種設備:
1. <meta name="viewport" content="width=device-width, initial-scale=1" />
2. 不要使用絕對寬度
3. 字體大小和長寬邊距屬性不要用」px」,應該用相對大小的「rem」
4. 使用流動佈局
- 若是寬度過小,放不下兩個元素,後面的元素會自動滾動到前面元素的下方,不會在水平方向overflow(溢出),避免了水平滾動條的出現
5. link標籤的media屬性
- <link rel="stylesheet" type="text/css" media="screen and (min-width: 600px) and (max-device-width: 980px)"
href="css600-980.css" />
6. Media Query
7. 圖片的自適應(自動縮放)
- img{max-width: 100%;}
- 最好仍是根據不一樣大小的屏幕,加載不一樣分辨率的圖片
複製代碼
1. Unicode是'字符集',utf-8是'編碼規則'
(以8位爲一個編碼單位的可變長編碼,會將一個碼位編碼爲1到4個字節)
2. 字符集:爲每個字符分配一個惟一的ID
編碼規則:將碼位轉爲字節序序列的規則
例如:'知'的碼位是30693,記做U+7735(16進製爲0x77E5)
'Unicode與utf-8關係':
U+0000 - U+007F:0XXXXXXX
U+0080 - U+07FF:110XXXXX 10XXXXXX
U+0800 - U+FFFF:1110XXXX 10XXXXXX 10XXXXXX
U+10000 - U+1FFFF:11110XXX 10XXXXXX 10XXXXXX 10XXXXXX
3. utf-16使用2或4字節來保存,utf-32使用4字節保存
'GBK與utf-8':
- UTF-8包含全世界全部國家須要用到的字符,是國際編碼,通用性強。
- GBK是國家標準GB2312基礎上擴容後兼容GB2312的標準。
- GBK的文字編碼是用'雙字節'來表示的,爲了區分中文,將其最高位都設定成1,通用性比UTF8差。
複製代碼
補充: React-router中的Link和Route的區別html
const promise = new Promise((resolve, reject) => {
console.log('a');
resolve();
console.log('b');
});
promise.then(() => {
console.log('c');
});
console.log('d');
// a b d c,Promise的異步執行
複製代碼
(function(x) {
return (function(y) {
console.log(x);
})(2);
})(1);
// 1,閉包問題
複製代碼
pi = 0;
radius = 1;
function circum(radius) {
radius = 3;
pi = 3.14;
console.log(2 * pi * radius); // 18.14
console.log(arguments[0]); // 3
}
circum(2);
console.log(pi); // 3.14
console.log(radius); // 1
函數內修改了radius 修改的是"形式參數",修改的pi是"全局的"pi
複製代碼
與下述狀況相同前端
var pi = 0;
var radius = 1;
function circum(radius) {
radius = 3;
pi = 3.14;
console.log(2 * pi * radius); // 18.84
console.log(arguments[0]); // 3
}
circum(radius);
console.log(pi); // 3.14
console.log(radius); // 1
複製代碼
補充java
function foo(a, b){
arguments[0] = 9;
arguments[1] = 99;
console.log(a, b); //9, 99
}
foo(1, 10);
function foo(a, b){
a = 8;
b = 88;
console.log(arguments[0], arguments[1]); //8, 88
}
foo(1, 10);
// ES6的默認函數不會改變arguments類數組對象值
function foo(a=1, b=10){
arguments[0] = 9;
arguments[1] = 99;
console.log(a, b); //1, 10
}
foo();
// 實例
function f2(a) {
console.log(a);
var a;
console.log(a);
console.log(arguments[0])
}
f2(10)
通過變量提高後:
function f2(a) {
var a;
console.log(a);
console.log(a);
console.log(arguments[0])
}
f2(10);
var a會被概括,因爲a已經有值,故不會變爲undefined
複製代碼
穩定排序:
插入排序 [1] ,冒泡排序 [2] ,歸併排序 [3] ,基數排序 [4] ,計數排序 [5]
不穩定排序:
快速排序 [1],簡單選擇排序 [2],希爾排序 [3],堆排序 [4]
複製代碼
var obj = {};
var arr = [];
var funcInstance = new (function (){});
var isNull = null;
console.log(typeof obj === 'object'); //true
console.log(typeof arr === 'object'); //true
console.log(typeof funcInstance == 'object'); //true
console.log(typeof isNull === 'object'); // true
// constructor
({}).constructor === Object; //true
([]).constructor === Array; //true
// instanceof
({}) instanceof Object; //true
([]) instanceof Array; //true
// toString: 將當前對象以字符串的形式返回
console.log(Object.prototype.toString.call(obj)); //[object Object]
console.log(Object.prototype.toString.call(arr)); //[object Array]
console.log(Object.prototype.toString.call(null)); //[object Null]
複製代碼
var a = {};
var b = {name:"ZS"};
var c = {};
c[a] = "demo1";
c[b] = "demo2";
console.log(c[a]); // demo2
console.log(c); // Object {[object Object]: "demo2"}
c[a]、c[b]隱式的將對象a,b使用了toString()方法進行了轉換,而後再對屬性賦值。
即:Object.prototype.toString.call(a) ==> [object Object]
所以,c = { [object Object]: 'demo1'} ==> c = {[object Object]: 'demo2' }
複製代碼
function log() {
// var arr = [].slice.call(arguments);
var arr = Array.from(arguments);
var res = '';
arr.forEach(elem => {
res += elem + ' ';
});
console.log(`(app)${res}`);
}
// 測試
log('hello', 'world');
log('hello world');
複製代碼
function toTreeData(data){
var pos={};
var tree=[];
var i=0;
while(data.length!=0){
if(data[i].pid==0){
tree.push({
id:data[i].id,
text:data[i].text,
children:[]
});
pos[data[i].id]=[tree.length-1];
data.splice(i,1);
i--;
}else{
var posArr=pos[data[i].pid];
if(posArr!=undefined){
var obj=tree[posArr[0]];
for(var j=1;j<posArr.length;j++){
obj=obj.children[posArr[j]];
}
obj.children.push({
id:data[i].id,
text:data[i].text,
children:[]
});
pos[data[i].id]=posArr.concat([obj.children.length-1]);
data.splice(i,1);
i--;
}
}
i++;
if(i>data.length-1){
i=0;
}
}
return tree;
}
var data=[
{id:1,pid:0,text:'A'},
{id:2,pid:4,text:"E[父C]"},
{id:3,pid:7,text:"G[父F]"},
{id:4,pid:1,text:"C[父A]"},
{id:5,pid:6,text:"D[父B]"},
{id:6,pid:0,text:'B'},
{id:7,pid:4,text:"F[父C]"}
];
var result = toTreeData(data);
console.log(result);
複製代碼
第二種思路:web
function treeObj(originObj) {
// 深拷貝
let obj = {};
for(key in originObj) {
var val = originObj[key];
// arguments的callee屬性指向擁有這個 arguments 對象的函數
obj[key] = typeof val === 'object'? arguments.callee(val):val;
}
obj['children'] = [];
return obj;
}
function toTreeData(data, attributes) {
let resData = data;
let tree = [];
// 找根節點
for(let i = 0; i < resData.length; i++) {
if(resData[i][attributes.parentId] === ''
||
resData[i][attributes.parentId] === null) {
tree.push(treeObj(resData[i]));
// 刪除掉已經放入tree中的根節點
resData.splice(i, 1);
i--;
}
}
// 找尋子樹
return run(tree);
function run(childArr) {
if(resData.length !== 0) {
for(let i = 0; i < childArr.length; i++) {
for(let j = 0; j < resData.length; j++) {
if(childArr[i][attributes.id] === resData[j][attributes.parentId]) {
let obj = treeObj(resData[j]);
childArr[i].children.push(obj);
// 刪除加入樹中的節點
resData.splice(j, 1);
j--;
}
}
run(childArr[i].children);
}
}
return tree;
}
}
let allRes = [
{
id: 4,
resName: "刪除角色",
parentId: 2
},
{
id: 3,
resName: "編輯角色",
parentId: ''
},
{
id: 2,
resName: "設置權限",
parentId: ''
},
{
id: 5,
resName: "添加用戶",
parentId: 4
},
{
id: 6,
resName: "更新用戶",
parentId: 4
},
{
id: 7,
resName: "刪除用戶",
parentId: 6
},
{
id: 8,
resName: "重置密碼",
parentId: 3
},
{
id: 9,
resName: "添加地區",
parentId: 5
},
{
id: 10,
resName: "編輯地區",
parentId: 6
}
];
let data = allRes;
// 屬性配置信息
let attributes = {
id: 'id',
parentId: 'parentId',
};
let treeData = toTreeData(data, attributes);
console.log(treeData);
複製代碼
// 1. Object.assign
let foo = {
a: 1,
b: 2,
c: {
d: 1,
}
}
let bar = {};
Object.assign(bar, foo);
foo.a++;
foo.a === 2 //true
bar.a === 1 //true
foo.c.d++;
foo.c.d === 2 //true
bar.c.d === 1 //false
bar.c.d === 2 //true
Object.assign()是一種能夠對非嵌套對象進行深拷貝的方法;
若是對象中出現嵌套狀況,那麼其對被嵌套對象的行爲就成了普通的淺拷貝。
// 2. JSON.parse和JSON.stringify
var obj1 = { body: { a: 10 } };
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.body.a = 20;
console.log(obj1); // { body: { a: 10 } }
console.log(obj2); // { body: { a: 20 } }
console.log(obj1 === obj2); // false
console.log(obj1.body === obj2.body); // false
用JSON.stringify把對象轉成字符串,再用JSON.parse把字符串轉成新的對象。
可是,會破壞原型鏈,而且沒法拷貝屬性值爲function的屬性
// 3. 遞歸
var json1={
"name":"shauna",
"age":18,
"arr1":[1,2,3,4,5],
"string":'got7',
"arr2":[1,2,3,4,5],
"arr3":[{"name1":"shauna"},{"job":"web"}]
};
var json2={};
function copy(obj1,obj2){
var obj2 = obj2 || {};
for(var name in obj1){
if(typeof obj1[name] === "object"){
obj2[name]= (obj1[name].constructor===Array)?[]:{};
copy(obj1[name],obj2[name]);
}else{
obj2[name]=obj1[name];
}
}
return obj2;
}
json2=copy(json1,json2)
json1.arr1.push(6);
alert(json1.arr1); //123456
alert(json2.arr1); //12345
複製代碼
// 遞歸
function flatten(arr){
var res = [];
for(var i=0;i<arr.length;i++){
if(Array.isArray(arr[i])){
res = res.concat(flatten(arr[i]));
}else{
res.push(arr[i]);
}
}
return res;
}
複製代碼
回溯算法面試
下面的輸出是什麼?ajax
var array1 = Array(3);
array1[0] = 2;
var result = array1.map(elem => '1');
// ['1', empty * 2]
複製代碼
var setPerson = function(person) {
person.name = 'kevin';
person = {name: 'Nick'};
console.log(person.name); // Nick
person.name = 'Jay';
console.log(person.name); // Jay
}
var person = {name: 'Alan'};
setPerson(person);
console.log(person.name); // Kevin
複製代碼
var execFunc = () => console.log('a');
setTimeout(execFunc, 0);
console.log('000');
execFunc = () => console.log('b');
// '000', 'a'
複製代碼
補充:setTimeout沒法使用含參函數參數算法
window.setTimeout(hello(userName),3000);
這將使hello函數當即執行,並將'返回值'做爲調用句柄傳遞給setTimeout函數
// 方法1:
使用'字符串形式'能夠達到想要的結果:
window.setTimeout("hello(userName)",3000);
可是,此處的username變量必須處於全局環境下
// 方法2:
function hello(_name){
alert("hello,"+_name);
}
// 建立一個函數,用於返回一個無參數函數
function _hello(_name){
return function(){
hello(_name);
}
}
window.setTimeout(_hello(userName),3000);
使用_hello(userName)來返回一個不帶參數的函數句柄,從而實現了參數傳遞的功能
複製代碼
for(var i = {j: 0}; i.j < 5; i.j++) {
(function(i){
setTimeout(function() {
console.log(i.j);
}, 0);
})(JSON.parse(JSON.stringify(i)));
}
// 0, 1, 2, 3, 4
for(var i = {j: 0}; i.j < 5; i.j++) {
(function(i){
setTimeout(function() {
console.log(i.j);
}, 0);
})(i);
}
// 5, 5, 5, 5, 5
複製代碼
1.如何進行輸入去重?chrome
// 方法1:
function nonDup(arr){
var res = [];
for(var i = 0; i < arr.length; i++) {
if(res.indexOf(arr[i]) === -1) {
res.push(arr[i]);
}
}
return res;
}
// 方法2:
function nonDup(arr){
var res = new Set(arr);
return [...res];
}
// 方法3:
function nonDup(arr){
return arr.filter((elem, index) => {
return index === arr.indexOf(elem);
});
}
// 方法4:
Array.prototype.uniq = function () {
var hasNaN = false;
for(var i = 0; i < this.length; i++){
if(this[i] !== this[i]) hasNaN = true;
for(var j = i+1; j < this.length;){
if(this[i] === this[j] ||(hasNaN && this[j] !== this[j])){
this.splice(j,1);
}else{
j++;
}
}
}
return this;
}
複製代碼
2.實現鼠標滑過頭像顯示簡介
<!DOCTYPE html>
<html>
<head>
<style>
.div1{
width:100px;
height:100px;
background-color:red;
border-radius: 50px;
}
.div2{
width:100px;
height:200px;
margin-top: 10px;
background-color:black;
display: none;
}
</style>
</head>
<body>
<div class='div1'></div>
<div class='div2'></div>
<script type="text/javascript">
var d1 = document.getElementsByClassName('div1')[0];
var d2 = document.getElementsByClassName('div2')[0];
var timer;
d1.addEventListener('mouseenter',function(){
timer = window.setTimeout(function(){d2.style.display="block"},300);
})
d1.addEventListener('mouseout',function(){
window.clearTimeout(timer);
d2.style.display="none";
})
</script>
</body>
</html>
複製代碼