面面試,收穫真的挺大的,感謝能有此次機會,感受打開了前進的路, 建議看到題後本身先寫一下試試,知其然還需知其因此然,把原理搞明白javascript
let str = 'abc'
function rev(str) {
let arr = str.split('')
let tem = []
for (let i = arr.length-1; i >= 0; i--) {
tem.push(arr[i])
}
return tem.join('')
}
rev(str)
console.log(rev(str))
複製代碼
// 冒泡排序: 隨便拿出一個數與後者比較,若是前者比後者大,那麼二者交換位置,
let arr = [5,2,3,1,4]
function bubbleSort(arr) {
let arrLen = arr.length
for (let i = 0; i < arrLen; i++){
for (let j = i; j < arrLen; j++){
let tempi = arr[i];
let tempj = arr[j];
if (tempi > tempj) {
arr[i] = tempj;
arr[j] = tempi;
}
}
}
return arr
}
console.log(bubbleSort(arr))
/* 快速排序 :
* 1. 以一個數爲基準(基準值能夠任意選擇,選擇中間的值容易理解
* 2. 按照順序,將每一個元素與"基準"進行比較,造成兩個子集,一個"小於3",另外一個"大於等於3"。
* 3. 對兩個子集不斷重複第一步和第二步,直到全部子集只剩下一個元素爲止
*/
let arr = [5, 2, 3, 1, 4]
function quickSort(arr) {
// 若是數組爲1那就不必比較了
 if (arr.length <= 1) { return arr }
// 取中間索引值
let pivotIndex = Math.floor(arr.length / 2)
// 獲取中間值
let pivot = arr.splice(pivotIndex, 1)[0]
let left = []
let right = []
for (let i = 0; i < arr.length; i ++) {
if(arr[i] < pivot) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
// 使用遞歸不斷重複這個過程
return quickSort(left).concat([pivot], quickSort(right))
}
console.log(quickSort(arr))
複製代碼
// 1. from && set
let arr = [1, 1, 4, 50, 50, 6, 2, 2]
let res = Array.from(new Set(arr))
console.log(res)
// 2. filter && indexOf
let arr = [2, 2, 33, 44, 33]
let res = arr.filter((item, index, arr) => {
return arr.indexOf(item) == index
})
console.log(res)
// 3. forEach && includes
let arr = [2, 2, 33, 44, 33]
let res = []
arr.forEach((item) => {
if (!res.includes(item)) {
res.push(item)
}
})
console.log(res)
// 4. filter && Map
let arr = [2, 2, 33, 44, 33]
const tem = new Map();
let res = arr.filter((item) => !tem.has(item) && tem.set(item, 1))
console.log(res)
複製代碼
let str = ' adb ddd '
let res = str.replace(/\s+/g, "")
console.log(res)
複製代碼
let str = 'asdasddsfdsfadsfdghdadsdfdgdasd';
function getMax(str) {
let obj = {};
for (let i in str) {
if (obj[str[i]]) {
obj[str[i]]++
} else {
obj[str[i]] = 1
}
}
let num = 0
let number = 0
for (var i in obj) {
//若是當前項大於下一項
if (obj[i] > num) {
//就讓當前值更改成出現最屢次數的值
num = obj[i]
number = i
}
}
console.log('最多的值是' +number+ '出現次數爲' + num);
}
getMax(str);
複製代碼
// 構造函數繼承
function Super(){
this.name = ["張三","李四"]
}
function Sub(){
Super.call(this)
}
let a = new Sub();
a.name.push("王五")
// 「張三","李四","王五" console.log(a.name); let b = new Sub() //// 「張三","李四"
console.log(b.name)
// Class 繼承
class Fathter {
constructor(name) {
this.name = name
}
hello() {
console.log('Hello, ' + this.name)
}
}
class Son extends Fathter {
constructor(name) {
// 記得用super調用父類的構造方法
super(name)
console.log(name)
}
}
let res = new Son('張三')
res.hello()
複製代碼
JSON.parse(JSON.stringify(obj));
複製代碼
function Foo(){
getName = function () {
console.log(1);
}
return this;
}
Foo.getName = function() {
console.log(2);
};
Foo.prototype.getName = function(){
console.log(3);
};
var getName = function(){
console.log(4);
};
function getName(){
console.log(5)
};
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); // 2
new Foo().getName(); // 3 至關於 var f = new Foo() f.getName()
new new Foo().getName(); // 3
// 這道題至關經典了 花點時間本身去看下吧
複製代碼
function fun() {
this.a = 0
this.b = function() {
console.log(this)
console.log(this.a)
}
}
fun.prototype = {
b: function() {
this.a = 20
console.log(this.a)
},
c: function() {
this.a = 30
console.log(this.a)
}
}
var my_fun = new fun();
//私有方法 this=>my_fun
my_fun.b();
console.log(my_fun.a);
//公有方法 this=>my_fun this.a = 30(私有屬性a修改成30)
my_fun.c();
console.log(my_fun.a);
var my_fun2 = new fun();
console.log(my_fun2.a);
//this=>my_fun2.__proto__ 當前實例·經過原型鏈在共有屬性增長的了一a:30
my_fun2.__proto__.c();
console.log(my_fun2.a);
console.log(my_fun2.__proto__.a);
// 0,0,30,30,0,30,0,30
複製代碼
function setName(obj){
obj.name = "Tom"
obj = new Object()
obj.name = 'Mike'
}
var person = new Object()
setName(person)
console.log(person.name) // "Tom"
複製代碼
// ES5 的寫法
let arr = [ 2,4,5,1]
console.log(Math.min.apply(null, arr))
// ES6 的寫法
console.log(Math.max(...[14, 3, 77, 30]))
複製代碼
let num = 12345678
console.log(num.toLocaleString())
複製代碼
let num = 12345678
function toThousands(num) {
var result = '', counter = 0;
num = (num || 0).toString();
for (var i = num.length - 1; i >= 0; i--) {
counter++;
result = num.charAt(i) + result;
if (!(counter % 3) && i != 0) { result = ',' + result; }
}
return result;
}
console.log(toThousands(num))
複製代碼
// 3-1
let num = 12345678
function toThousands(num) {
return (num || 0).toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
}
console.log(toThousands(num))
// 3-2
let num = 12345678
function toCurrency(num){
var parts = num.toString().split('.');
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
return parts.join('.');
}
console.log(toCurrency(num))
複製代碼
相關連接前端
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
console.log(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
複製代碼
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
console.log(object.getNameFunc()()); // the window
複製代碼
var length = 1
function fn() {
console.log(this.length)
}
var obj = {
length: 3,
me:function(fn){
fn() // 1
arguments[0]() // 2
}
}
obj.me(fn, 1)
複製代碼
let str = '你好,abc'
function getLength(str){
let length = 0
let reg = /[\u4e00-\u9fa5]/
for (let i = 0; i < str.length; i++) {
if (reg.test(str.charAt(i))) {
length +=2
} else {
length ++
}
}
return length
}
console.log(getLength(str))
複製代碼
利用 Proxyvue
參考 -- 摒棄 Object.defineProperty,基於 Proxy 的觀察者機制探索java
prototype是構造函數的屬性。node
proto 是每一個實例都有的屬性,能夠訪問 [[prototype]] 屬性。webpack
實例的__proto__ 與其構造函數的prototype指向的是同一個對象。ios
function Student(name) {
this.name = name;
}
Student.prototype.setAge = function(){
this.age=20;
}
let Jack = new Student('jack');
console.log(Jack.__proto__);
//console.log(Object.getPrototypeOf(Jack));;
console.log(Student.prototype);
console.log(Jack.__proto__ === Student.prototype);//true
。
複製代碼
參考劉小夕解答git
var a = {n:1};
var b = a; // 持有a,以回查
a.x = a = {n:2};
console.log(a.x);// --> undefined
console.log(b.x);// --> {n:2}
複製代碼
var y = 1;
if (function f(){}) {
y += typeof f;
}
console.log(y); // 1undefined
複製代碼
var a = 0
function b(){
console.log(a) // fun a
a = 10
console.log(a) // 10
return;
function a(){}
}
b()
console.log(a) // 0
複製代碼
概念:
1. 在事件被觸發n秒後再執行回調,若是在這n秒內又被觸發,則從新計時。
2. 屢次觸發事件後,事件處理函數只執行一次,而且是在觸發操做結束時執行。
應用場景:
1. 文本輸入的驗證(連續輸入文字後發送 ajax 請求進行驗證,驗證一次就好)
2. 給按鈕加函數防抖防止表單屢次提交。
生活實例:
若是有人進電梯(觸發事件),那電梯將在10秒鐘後出發(執行事件監聽器),這時若是又有人進電梯了(在10秒內再次觸發該事件),咱們又得等10秒再出發(從新計時)。
代碼
function debounce(func, interval = 100){
let timer;
return (...args) => {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
func.apply(func, args);
}, interval);
}
}
複製代碼
概念:
規定一個單位時間,在這個單位時間內,只能有一次觸發事件的回調函數執行,若是在同一個單位時間內某事件被觸發屢次,只有一次能生效
應用場景:
滾動刷新如 touchmove, mousemove, scroll。
生活實例:(實例忘記參考誰的了,看到我添加鏈接)
1. 咱們知道目前的一種說法是當 1 秒內連續播放 24 張以上的圖片時,在人眼的視覺中就會造成一個連貫的動畫,因此在電影的播放(之前是,如今不知道)中基本是以每秒 24 張的速度播放的,爲何不 100 張或更可能是由於 24 張就能夠知足人類視覺需求的時候,100 張就會顯得很浪費資源
2. 假設電梯一次只能載一人的話,10 我的要上樓的話電梯就得走 10 次,是一種浪費資源的行爲;而實際生活正顯然不是這樣的,當電梯裏有人準備上樓的時候若是外面又有人按電梯的話,電梯會再次打開直到滿載位置,從電梯的角度來講,這時一種節約資源的行爲(相對於一次只能載一我的)。。
代碼
function throttle(fn, interval = 100) {
let canRun = true; // 經過閉包保存一個標記
return (...args) => {
if (!canRun) return; // 在函數開頭判斷標記是否爲true,不爲true則return
canRun = false; // 當即設置爲false
setTimeout(() => { // 將外部傳入的函數的執行放在setTimeout中
fn.apply(fn, args)
// 最後在setTimeout執行完畢後再把標記設置爲true(關鍵)表示能夠執行下一次循環了。當定時器沒有執行的時候標記永遠是false,在開頭被return掉
canRun = true;
}, interval);
};
}
複製代碼
function foo(a) {
var a;
return a;
}
function bar(a) {
var a = 'bye';
return a;
}
[foo('hello'), bar('hello')] // hello bye
// 在兩個函數裏, a做爲參數其實已經聲明瞭, 因此 var a; var a = 'bye' 其實就是 a; a ='bye'
複製代碼
原型鏈解決的主要是繼承問題。
每一個對象擁有一個原型對象,經過 proto (讀音: dunder proto) 指針指向其原型對象,並從中繼承方法和屬性,同時原型對象也可能擁有原型,這樣一層一層,最終指向 null(==Object.proptotype.proto 指向的是null==)。這種關係被稱爲原型鏈 (prototype chain),經過原型鏈一個對象能夠擁有定義在其餘對象中的屬性和方法。 構造函數 Parent、Parent.prototype 和 實例 p 的關係以下:(==p.proto === Parent.prototype==)
var name = "World!";
(function() {
if(typeof name=== 'undefined'){
var name='Jack';
console.log('Goodbye'+name);
} else {
console.log('hello'+name);
}
})()
// Goodbye Jack
複製代碼
跳到 n 階假設有 f(n)種方法。
往前倒退,若是青蛙最後一次是跳了 2 階,那麼以前有 f(n-2)種跳法; 若是最後一次跳了 1 階,那麼以前有 f(n-1)種跳法。
因此:f(n) = f(n-1) + f(n-2)。就是斐波那契數列
複製代碼
參考
class Chameleon {
static colorChange(newColor) {
this.newColor = newColor
return this.newColor
}
constructor({ newColor = 'green' } = {}) {
this.newColor = newColor
}
}
const freddie = new Chameleon({ newColor: 'purple' })
freddie.colorChange('orange')
// 會報錯
colorChange是一個靜態方法。靜態方法被設計爲只能被建立它們的構造器使用(也就是 Chameleon),而且不能傳遞給實例。由於 freddie 是一個實例,靜態方法不能被實例使用,所以拋出了 TypeError 錯誤。
複製代碼
function* generator(i) {
yield i;
yield i * 2;
}
const gen = generator(10);
console.log(gen.next().value); // 10
console.log(gen.next().value); // 20
通常的函數在執行以後是不能中途停下的。可是,生成器函數卻能夠中途「停下」,以後能夠再從停下的地方繼續。當生成器遇到yield關鍵字的時候,會生成yield後面的值。注意,生成器在這種狀況下不 返回 (return )值,而是 生成 (yield)值。
首先,咱們用10做爲參數i來初始化生成器函數。而後使用next()方法一步步執行生成器。第一次執行生成器的時候,i的值爲10,遇到第一個yield關鍵字,它要生成i的值。此時,生成器「暫停」,生成了10。
而後,咱們再執行next()方法。生成器會從剛纔暫停的地方繼續,這個時候i仍是10。因而咱們走到了第二個yield關鍵字處,這時候須要生成的值是i*2,i爲10,那麼此時生成的值即是20。因此這道題的最終結果是10,20。
複製代碼
const num = parseInt("7*6", 10);
console.log(num) // 7
parseInt檢查字符串中的字符是否合法. 一旦遇到一個在指定進制中不合法的字符後,當即中止解析而且忽略後面全部的字符。
複製代碼
function create(proto) {
function F() {};
F.prototype = proto;
F.prototype.constructor = F;
return new F();
}
複製代碼
zhangxiang958-理解 ES6 generator
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
<div id='app'>
<h3>姓名</h3>
<p>{{name}}</p>
<h3>年齡</h3>
<p>{{age}}</p>
</div>
</body>
</html>
<script>
document.addEventListener('DOMContentLoaded', function(){
let opt = {el:'#app', data:{name:'檢索中...', age:30}}
let vm = new Vue(opt)
setTimeout(() => {
opt.data.name = '王永峯'
}, 2000);
}, false)
class Vue{
constructor(opt){
this.opt = opt
this.observe(opt.data)
let root = document.querySelector(opt.el)
this.compile(root)
}
// 爲響應式對象 data 裏的每個 key 綁定一個觀察者對象
observe(data){
Object.keys(data).forEach(key => {
let obv = new Observer()
data["_"+key] = data[key]
// 經過 getter setter 暴露 for 循環中做用域下的 obv,閉包產生
Object.defineProperty(data, key, {
get(){
Observer.target && obv.addSubNode(Observer.target);
return data['_'+key]
},
set(newVal){
obv.update(newVal)
data['_'+key] = newVal
}
})
})
}
// 初始化頁面,遍歷 DOM,收集每個key變化時,隨之調整的位置,以觀察者方法存放起來
compile(node){
[].forEach.call(node.childNodes, child =>{
if(!child.firstElementChild && /\{\{(.*)\}\}/.test(child.innerHTML)){
let key = RegExp.$1.trim()
child.innerHTML = child.innerHTML.replace(new RegExp('\\{\\{\\s*'+ key +'\\s*\\}\\}', 'gm'),this.opt.data[key])
Observer.target = child
this.opt.data[key]
Observer.target = null
}
else if (child.firstElementChild)
this.compile(child)
})
}
}
// 常規觀察者類
class Observer{
constructor(){
this.subNode = []
}
addSubNode(node){
this.subNode.push(node)
}
update(newVal){
this.subNode.forEach(node=>{
node.innerHTML = newVal
})
}
}
</script>
複製代碼
提取公共模塊,區分開發環境,移除重複沒必要要的 css 和 js 文件等方面說。
使用 v-for更新已渲染的元素列表時,默認用就地複用策略。列表數據修改的時候,他會根據key值去判斷某個值是否修改:若是修改,則從新渲染這一項;不然複用以前的dom,僅修改value值。
函數式組件,即無狀態,沒法實例化,內部沒有任何生命週期處理方法,很是輕量,於是渲染性能高,特別適合用來只依賴外部數據傳遞而變化的組件。
關於 Vue 編譯原理這塊的總體邏輯主要分三個部分,也能夠說是分三步,這三個部分是有先後關係的:
該題是遇到問題最多的 根據自身狀況回答
vw: 兼容性問題 ios八、安卓4.4及以上才徹底支持
rem:和根元素font-size值強耦合,系統字體放大或縮小時,會致使佈局錯亂;弊端之二:html文件頭部需插入一段js代碼
重繪和迴流是渲染步驟中的一小節,可是這兩個步驟對於性能影響很大。
迴流一定會發生重繪,重繪不必定會引起迴流。迴流所需的成本比重繪高的多,改變深層次的節點極可能致使父節點的一系列迴流。
重繪和迴流其實和 Event loop 有關
Load 事件觸發表明頁面中的 DOM,CSS,JS,圖片已經所有加載完畢。
DOMContentLoaded 事件觸發表明初始的 HTML 被徹底加載和解析,不須要等待 CSS,JS,圖片加載。
因爲用戶訪問源站業務有性能瓶頸,經過cdn技術把源站的內容緩存到多個節點。用戶向源站域名發起請求時,請求會被調度至最接近用戶的服務節點,直接由服務節點直接快速響應,有效下降用戶訪問延遲,提高可用性。
參考import、require、export、module.exports 混合使用詳解
/* 浮動佈局 */
.layout.float .left{
float:left;
width:300px;
background: red;
}
.layout.float .center{
background: yellow;
}
.layout.float .right{
float:right;
width:300px;
background: blue;
}
/* 絕對定位佈局 */
.layout.absolute .left-center-right>div{
position: absolute;
}
.layout.absolute .left{
left:0;
width: 300px;
background: red;
}
.layout.absolute .center{
left: 300px;
right: 300px;
background: yellow;
}
.layout.absolute .right{
right:0;
width: 300px;
background: blue;
}
/* flex佈局 */
.layout.flexbox{
margin-top: 110px;
}
.layout.flexbox .left-center-right{
display: flex;
}
.layout.flexbox .left{
width: 300px;
background: red;
}
.layout.flexbox .center{
flex:1;
background: yellow;
}
.layout.flexbox .right{
width: 300px;
background: blue;
}
複製代碼
按照固定寬高和不固定寬高分類各說幾個方法