天天看点

前端面试题集锦

 内存

栈内存:存储值类型,变量。

堆内存:复杂类型的数据,对象等。其中放栈内存中的变量存储的是在堆内存中的地址,从而指向堆内存。

div元素水平垂直居中的方法

第一种:

<style>
        .a {
            height: 300px;
            background-color: hotpink;
            position: relative;
        }
        
        .b {
            width: 100px;
            height: 100px;
            background-color: lawngreen;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            margin: auto;
        }
</style>
<body>
    <div class="a">
        <div class="b"></div>
    </div>
</body>
           

第二种:

<style>
        .a {
            height: 300px;
            background-color: hotpink;
            position: relative;
        }
        
        .b {
            width: 100px;
            height: 100px;
            background-color: lawngreen;
            position: absolute;
            margin: auto;
            left: 50%;
            top: 50%;
            transform: translate(-50%, -50%);
        }
</style>
           

cookie和session 、sessionstorage和localstorage

cookie:Cookie是一段不超过4KB的小型文本数据,由一个名称(Name)、一个值(Value)和其它几个用于控制Cookie有效期、安全性、使用范围的可选属性组成。

cookie数据存放在客户的浏览器上。cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗。Cookie的maxAge决定着Cookie的有效期,单位为秒(Second)。Cookie中通过getMaxAge()方法与setMaxAge(int maxAge)方法来读写maxAge属性。

session:session,服务器为了保存用户状态而创建的一个特殊的对象。当浏览器第一次访问服务器时,服务器创建一个session对象(该对象有一个唯一的id,一般称之为sessionId),服务器会将sessionId以cookie的方式发送给浏览器。当浏览器再次访问服务器时,会将sessionId发送过来,服务器依据sessionId就可以找到对应的session对象。

session数据放在服务器上。session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。

sessionstorage和localstorage的区别:

localStorage生命周期是永久,除非用户清除localStorage信息,否则这些信息将永远存在;

sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过它存储的数据也就被清空了。

localStorage和sessionStorage一样都是用来存储客户端临时信息的对象。

详细请见转载:cookie、sessionStorage和localStorage的区别_浮生离梦的博客-CSDN博客(写的很好!!!)

http缓存:常见的http缓存只能缓存get请求响应的资源

消除数组中的重复元素

var b = [1, 2, 1, 2, 3, 5, "q", "q", [1],[1, 2],[1]];

var resualt = new Set(b);//将数组中重复元素删除,并以对象形式返回

resualt = Array.from(resualt);//将对象转换为数组

console.log(resualt);
           

结果:

前端面试题集锦

将数组进行全排列,生成一个新数组

例:["a,b,c"]

全排序为["a,b,c","a,c,b","b,a,c","b,c,a","c,a,b","c,b,a"]

function Allsort1(arr) {
    var arr1 = arr[0].split(",");

    function swap(arr, i, j) {
        if (i != j) {
            var temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }
    }
    var Arr = [];
    //此方法最主要是交换的思路
    function perm(arr) {
        (function fn(n) { //为第n个位置选择元素 
            for (var i = n; i < arr.length; i++) {
                swap(arr, i, n);
                if (n + 1 < arr.length - 1) //根据下标a(b+1) 不是最后一项,判断数组中剩余的待全排列的元素是否大于1个 
                    fn(n + 1); //从第n+1个下标进行全排列 
                else {
                    Arr.push(arr.toString());
                }
                swap(arr, i, n);
            }
        })(0);
    }
    perm(arr1);
    return Arr;
}
           

React的四种hook

useState():状态钩子。

纯函数没有状态,useState() 用于为函数组件引入状态。

useContext():共享状态钩子。

作用就是可以做状态的分发,在React16.X以后支持,避免了react逐层通过Props传递数据。

useReducer():Action钩子。

在使用React的过程中,如遇到状态管理,一般会用到Redux,而React本身是不提供状态管理的。而useReducer()提供了状态管理。首先,关于redux我们都知道,其原理是通过用户在页面中发起action,从而通过reducer方法来改变state,从而实现页面和状态的通信。而Reducer的形式是(state, action) => newstate。它接受reducer函数和状态的初始值作为参数,返回一个数组,其中第一项为当前的状态值,第二项为发送action的dispatch函数。

useEffect():副作用钩子。

可以用来更好的处理副作用,如异步请求等,Hooks 的 useEffect()也是为函数组件提供了处理副作用的钩子。

全局状态管理

vue 里通过 vuex实现全局状态管理,在react里可以通过redux或者mobx也可以实现全局状态管理。

js的数据类型

JavaScript的基本数据类型:

值类型 (基本类型) :字符串(String)、数字 (Number)、布尔 (Boolean)、对空(Null)、未定义(Undefined)、Symbol。

引用数据类型 :对象 (Object)、数组 (Array)、函数 (Function)。.

几种内部基本排序

插入排序

        直接插入排序:

        折半插入排序:

        希尔排序:

交换排序

        冒泡排序:

        快速排序:

选择排序

        简单选择排序:

        堆排序:

归并排序:

基数排序:

浏览器的内核

浏览器的内核是指支持浏览器运行的最核心的程序,分为两个部分的,一是渲染引擎,另一个是JS引擎。

主流浏览器

IE/Edge(Trident),Chrome(Webkit,blink ),Safari(Webkit),Opera(Presto,Webkit,blink ),Firefox(Mosaic)。

IE/Edge:微软的IE浏览器浏览器更新至IE10后,伴随着WIN10系统的上市,迁移到了全新的浏览器Edge。除了JS引擎沿用之前IE9就开始使用的查克拉(Chakra),渲染引擎使用了新的内核EdgeHTML(本质上不是对Trident的完全推翻重建,而是在Trident基础上删除了过时的旧技术支持的代码,扩展和优化了对新的技术的支持,所以被看做是全新的内核)

Safari:Safari自2003年面世,就一直是苹果公司的产品自带的浏览器,它使用的是苹果研发和开源的Webkit引擎。Webkit引擎包含WebCore排版引擎及JavaScriptCore解析引擎,均是从KDE的KHTML及KJS引擎衍生而来。Webkit2发布于2010年,它实现了元件的抽象画,提高了元件的重复利用效率,提供了更加干净的网页渲染和更高效的渲染效率。另外,Webkit也是苹果Mac OS X系统引擎框架版本的名称,主要用于Safari、Dashboard、Mail。

Chrome:提到Chrome浏览器,一般人会认为使用的Webkit内核,这种说法不完全准确。Chrome发布于2008年,使用的渲染内核是Chromium,它是fork自Webkit,但把Webkit梳理得更有条理可读性更高,效率提升明显。2013年,由于Webkit2和Chromium在沙箱设计上的冲突,谷歌联手Opera自研和发布了Blink引擎,逐步脱离了Webkit的影响。所以,可以这么认为:Chromium扩展自Webkit止于Webkit2,其后Chrome切换到了Blink引擎。另外,Chrome的JS引擎使用的V8引擎,应该算是最著名和优秀的开源JS引擎,大名鼎鼎的Node.js就是选用V8作为底层架构。

Firefox:火狐的内核Gecko也是开源引擎,任何程序员都能为其提供扩展和建议。火狐的JS引擎历经SpiderMonkey、TraceMonkey到现在的JaegerMonkey。其中JaegerMonkey部分技术借鉴了V8、JSCore和Webkit,算是集思广益。

Opera:Opera在2013年V12.16之前使用的是Opera Software公司开发的Presto引擎,之后连同谷歌研发和选择Blink作为Opera浏览器的排版内核。

题目1:

牛牛有一个只由字符'1'到'9'组成的长度为 n 的字符串 s ,现在牛牛可以截取其中一段长度为 k 的子串并且将该子串当作十进制的正整数,如对于子串"123",其对应的十进制数字就是123 。

牛牛想让这个正整数尽可能的大,请你帮助牛牛计算该正整数。

函数传入一个长度为 n  的字符串 s 和一个正整数 k ,请你返回答案。

输入例子1:

"321",2
      

输出例子1:

32
      
function maxValue(s, k) {
            // write code here
            var max = s[0];
            var x = 0;
            var Arr = [];
            var resualt = 0;
            for (var i = 0; i < s.length - 1; i++) {
                max = Math.max(max, s[i + 1]);
            }
            for (var i = 0; i < s.length; i++) {
                if (s[i] == max) {
                    x = i;
                    Arr.push(s.slice(x, x + k));
                }
            }
            max = Arr[0];
            for (var i = 0; i < Arr.length - 1; i++) {
                max = Math.max(max, Arr[i + 1]);
            }
            resualt = parseInt(max);
            return resualt;

        }
module.exports = {
    maxValue : maxValue
};
           

 补充知识点:*数组的各种用法(js)

创建数组

var array-name = [item1, item2, ...];      
var cars = ["Saab", "Volvo", "BMW"];
           

注:不要最后一个元素之后写逗号

使用 JavaScript 关键词 new

var cars = new Array("Saab", "Volvo", "BMW");
           

访问数组元素

通过引用索引号(下标号)来引用某个数组元素。

var name = cars[0];
           

数组索引从 0 开始。

数组是对象

数组是一种特殊类型的对象。在 JavaScript 中对数组使用 typeof 运算符会返回 "object"。

可以使用Array.isArray()判断是否为数组。

可以在数组保存对象。可以在数组中保存函数。甚至可以在数组中保存数组:

myArray[0] = Date.now;
myArray[1] = myFunction;
myArray[2] = myCars;
           

数组属性和方法

length 属性

返回数组的长度(数组元素的数目)。

遍历数组

for循环、Array.foreach() 函数:

var fruits, text;
fruits = ["Banana", "Orange", "Apple", "Mango"];

text = "<ul>";
fruits.forEach(myFunction);
text += "</ul>";

function myFunction(value) {
  text += "<li>" + value + "</li>";
}
           

添加或删除数组元素

pop() 方法从数组中删除最后一个元素,返回“被弹出”的值:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var x = fruits.pop();    // 从 fruits 删除最后一个元素("Mango"),x 的值是 "Mango"
           

push() 方法(在数组结尾处)向数组添加一个新的元素,返回新数组的长度:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
var x =  fruits.push("Kiwi");   //  向 fruits 添加一个新元素,x 的值是 5
           

shift() 方法会删除首个数组元素,并把所有其他元素“位移”到更低的索引,返回被“位移出”的字符串。

unshift() 方法(在开头)向数组添加新元素,并“反向位移”旧元素,返回新数组的长度。

也可以使用 length 属性向数组添加新元素:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits[fruits.length] = "Lemon";
           

 既然 JavaScript 数组属于对象,其中的元素就也可以使用 JavaScript delete 运算符来删除:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
delete fruits[0];           // 把 fruits 中的首个元素改为 undefined
           

但是使用 delete 会在数组留下未定义的空洞,所以推荐使用pop()或shift()。

把数组转换为字符串

toString() 把数组转换为数组值(逗号分隔)的字符串。

var fruits = ["Banana", "Orange", "Apple", "Mango"];
document.getElementById("demo").innerHTML = fruits.toString();
           

结果:

Banana,Orange,Apple,Mango
           

join() 方法也可将所有数组元素结合为一个字符串,还可以规定分隔符。

var fruits = ["Banana", "Orange","Apple", "Mango"];
document.getElementById("demo").innerHTML = fruits.join(" * "); 
           

结果:

Banana * Orange * Apple * Mango
           

拼接数组

splice() 方法可用于向数组添加新项,返回一个包含已删除项的数组:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(2, 0, "Lemon", "Kiwi");
           

第一个参数(2)定义了应添加新元素的位置(拼接)。

第二个参数(0)定义应删除多少元素。

其余参数(“Lemon”,“Kiwi”)定义要添加的新元素。

能够使用 splice() 在数组中不留“空洞”的情况下移除元素:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.splice(0, 1);        // 删除 fruits 中的第一个元素
           

合并(连接)数组

concat() 方法通过合并(连接)现有数组来创建一个新数组,不会更改现有数组,返回一个新数组:

var myGirls = ["Cecilie", "Lone"];
var myBoys = ["Emil", "Tobias", "Linus"];
var myChildren = myGirls.concat(myBoys);   // 连接 myGirls 和 myBoys
           

可以使用任意数量的数组参数:(三个数组)

var arr1 = ["Cecilie", "Lone"];
var arr2 = ["Emil", "Tobias", "Linus"];
var arr3 = ["Robin", "Morgan"];
var myChildren = arr1.concat(arr2, arr3);   // 将arr1、arr2 与 arr3 连接在一起
           

也可以将值作为参数:

var arr1 = ["Cecilie", "Lone"];
var myChildren = arr1.concat(["Emil", "Tobias", "Linus"]); 
           

裁剪数组

slice() 方法用数组的某个片段切出新数组,创建一个新数组,不会从原数组中删除任何元素。

var fruits = ["Banana", "Orange", "Lemon", "Apple", "Mango"];
var citrus = fruits.slice(1); 
           

可接受两个参数,比如 (1, 3)。

该方法会从开始参数选取元素,直到结束参数(不包括)为止。

如果结束参数被省略,比如第一个例子,则 slice() 会切出数组的剩余部分。

自动 toString()

如果需要原始值,则 JavaScript 会自动把数组转换为字符串。下面两个例子将产生相同的结果:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
document.getElementById("demo").innerHTML = fruits.toString(); 
           
var fruits = ["Banana", "Orange", "Apple", "Mango"];
document.getElementById("demo").innerHTML = fruits; 
           

数组排序

sort() 方法以字母顺序对数组进行排序:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();            // 对 fruits 中的元素进行排序
           

反转数组

reverse() 方法反转数组中的元素,可以使用它以降序对数组进行排序:

var fruits = ["Banana", "Orange", "Apple", "Mango"];
fruits.sort();            // 对 fruits 中的元素进行排序
fruits.reverse();         // 反转元素顺序
           

数字排序

当 sort() 函数比较两个值时,会将值发送到比较函数:function(a, b){return a-b},并根据所返回的值(负、零或正值)对这些值进行排序。

通过一个比值函数让sort() 函数按照数字顺序对值进行排序:

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return a - b}); 
           

使用相同的技巧对数组进行降序排序:

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return b - a}); 
           

以随机顺序排序数组

var points = [40, 100, 1, 5, 25, 10];
points.sort(function(a, b){return 0.5 - Math.random()}); 
           

查找最高(或最低)的数组值

在对数组进行排序之后,您能够使用索引来获得最高或最低值。

也可以使用 Math.max.apply 来查找数组中的最高值:

function myArrayMax(arr) {
    return Math.max.apply(null, arr);
}
           

Math.max.apply([1, 2, 3]) 等于 Math.max(1, 2, 3)。

可以使用 Math.min.apply 来查找数组中的最低值:

function myArrayMin(arr) {
    return Math.min.apply(null, arr);
}
           

Math.min.apply([1, 2, 3]) 等于 Math.min(1, 2, 3)。

排序对象数组

JavaScript 数组经常会包含对象:

var cars = [
{type:"Volvo", year:2016},
{type:"Saab", year:2001},
{type:"BMW", year:2010}];
           

即使对象拥有不同数据类型的属性,sort() 方法仍可用于对数组进行排序。

解决方法是通过比较函数来对比属性值:

cars.sort(function(a, b){return a.year - b.year});
           

数组迭代

Array.forEach()

forEach() 方法为每个数组元素调用一次函数(回调函数)。

var txt = "";
var numbers = [45, 4, 9, 16, 25];
numbers.forEach(myFunction);

function myFunction(value, index, array) {
  txt = txt + value + "<br>"; 
}
           

三个参数: 

  • 项目值
  • 项目索引
  • 数组本身

Array.map() 

map() 方法通过对每个数组元素执行函数来创建新数组,不会对没有值的数组元素执行函数,不会更改原始数组。

这个例子将每个数组值乘以2:

var numbers1 = [45, 4, 9, 16, 25];
var numbers2 = numbers1.map(myFunction);

function myFunction(value, index, array) {
  return value * 2;
}
           

Array.filter()

filter() 方法创建一个包含通过测试的数组元素的新数组。

这个例子用值大于 18 的元素创建一个新数组:

var numbers = [45, 4, 9, 16, 25];
var over18 = numbers.filter(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}
           

Array.reduce()

reduce() 方法在每个数组元素上运行函数,以生成(减少它)单个值,在数组中从左到右工作,不会减少原始数组。

这个例子确定数组中所有数字的总和:

var numbers1 = [45, 4, 9, 16, 25];
var sum = numbers1.reduce(myFunction);

function myFunction(total, value, index, array) {
  return total + value;
}
           

此函数接受 4 个参数: 

  • 总数(初始值/先前返回的值)
  • 项目值
  • 项目索引
  • 数组本身

reduce() 方法能够接受一个初始值:

var sum = numbers1.reduce(myFunction, 100);
           

 Array.reduceRight()

reduceRight() 方法在每个数组元素上运行函数,以生成(减少它)单个值,在数组中从右到左工作,不会减少原始数组。

这个例子确定数组中所有数字的总和:

var numbers1 = [45, 4, 9, 16, 25];
var sum = numbers1.reduceRight(myFunction);

function myFunction(total, value, index, array) {
  return total + value;
}
           

Array.every()

every() 方法检查所有数组值是否通过测试。

这个例子检查所有数组值是否大于 18,返回true或false:

var numbers = [45, 4, 9, 16, 25];
var allOver18 = numbers.every(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}
           

 Array.some()

some() 方法检查某些数组值是否通过了测试。

这个例子检查某些数组值是否大于 18,只要有一个满足就是true:

var numbers = [45, 4, 9, 16, 25];
var someOver18 = numbers.some(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}
           

Array.indexOf()

indexOf() 方法在数组中搜索元素值并返回其位置。

注释:第一个项目的位置是 0,第二个项目的位置是 1,以此类推。

检索数组中的项目 "Apple":

var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.indexOf("Apple");
           

语法:array.indexOf(item, start)。

item 必需。要检索的项目。
start 可选。从哪里开始搜索。负值将从结尾开始的给定位置开始,并搜索到结尾。

如果未找到项目,Array.indexOf() 返回 -1。

如果项目多次出现,则返回第一次出现的位置。

Array.lastIndexOf()

Array.lastIndexOf() 与 Array.indexOf() 类似,但是从数组结尾开始搜索。

检索数组中的项目 "Apple":

var fruits = ["Apple", "Orange", "Apple", "Mango"];
var a = fruits.lastIndexOf("Apple");
           

Array.find()

find() 方法返回通过测试函数的第一个数组元素的值。

这个例子查找(返回)大于 18 的第一个元素的值:

var numbers = [4, 9, 16, 25, 29];
var first = numbers.find(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}
           

Array.findIndex()

findIndex() 方法返回通过测试函数的第一个数组元素的索引。

这个例子查找大于 18 的第一个元素的索引:

var numbers = [4, 9, 16, 25, 29];
var first = numbers.findIndex(myFunction);

function myFunction(value, index, array) {
  return value > 18;
}
           

数组 Const

用 const 声明的数组不能重新赋值,const 变量在声明时必须赋值:

const cars = ["Saab", "Volvo", "BMW"];
cars = ["Toyota", "Volvo", "Audi"];    // ERROR
           

关键字 const 有一定误导性。

它不定义常量数组。它定义的是对数组的常量引用。

因此,我们仍然可以更改常量数组的元素。

// 您可以创建常量数组:
const cars = ["Saab", "Volvo", "BMW"];

// 您可以更改元素:
cars[0] = "Toyota";

// 您可以添加元素:
cars.push("Audi");
           

用 const 声明的数组具有块作用域。

在块中声明的数组与在块外声明的数组不同。

继续阅读