前端面试总结(一)JS基础

1、async/await的本质

本质:Promise的语法糖。
优点:

(1)简化多余的{}嵌套,可读性友好;
(2)易于整理逻辑,编码体验良好.

缺点:

(1)屏蔽了原理,增加学习成本;
(2)所有的可以并发的操作,使用 async/await 都会变成串行操作,这应该是async/await的硬伤。

注意:

await一定出现在async标记的代码中,表示后面挂起一段线程代码,而await异步代码后在代码均表示回调代码。

   someCode1(); //片段1
   await Thask.Run(...); //片段2
   comeCode3(); //片段3

片段1与调用者同属一个线程,属同步代码。
片段2表示await引起的异步代码,另起一个线程。
片段3在await之后,表示该异步代码后的回调代码。

2、js实现异步的方法

(1)回调函数
/**
 * fn2可以视作一个延迟了500毫秒执行的异步函数。
 * 现在希望可以依次执行fn1,fn2,fn3。
 * 为了保证fn3在最后执行,可以把它作为fn2的回调函数:
 */
function fn3 () {
    console.log('Function 3')
}
function fn2 (f) {
    setTimeout(() => {
        console.log('Function 2')
        f()
    }, 500)
}
fn2(fn3);
/**
 * 此时,fn2和fn3完全耦合在一起,
 *  如果有多个类似的函数,很有可能会类似出现fn1(fn2(fn3(fn4(...))))的情况,即为回调地狱。
 */
(2)事件发布/订阅

发布/订阅模式也是诸多设计模式当中的一种,上述例子中fn2、n3都可以视作一个事件的发布者,只要执行它,就会发布一个事件。这个时候,我们可以通过一个事件的订阅者去批量订阅并处理这些事件,包括它们的先后顺序。

(3)Promise

用Promise的方式,就不需要额外地编写一个消息订阅者函数了,只需要异步函数返回一个Promise即可。

function fn1 () {
    console.log('Function 1')
}
//fn2是一个返回Promise的异步函数
function fn2 () {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('Function 2')
            resolve()
        }, 500)
    })
}
function fn3 () {
    console.log('Function 3')
}
fn1();
fn2().then(() => { fn3() });
输出:
Function 1
Function 2
Function 3
(4)generator

Promise能够化回调为链式,那么generator的办法则可以消灭那一大堆的Promise特征方法,比如then()。

(5)优雅的async/await
function fn1 () {
    console.log('Function 1')
}
function fn2 () {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('Function 2')
            resolve()
        }, 500)
    })
}
function fn3 () {
    console.log('Function 3')
}
async function asyncFunArr () {
    fn1()
    await fn2()
    fn3()
}
asyncFunArr()
输出:
Function 1
Function 2
Function 3

3、异步优先级

asycn=Promise>SetTimeout
规律:遇到SetTimeout和then(异步回调),加入队列,其他顺序执行(队列中先执行then)
async function async1() {
    console.log('1')
    await async2()
    console.log('2')
}
async function async2() {
    console.log('3')
}
console.log('4')
setTimeout(() => {
    console.log('5')
},0)
async1()
new Promise((resolve) => {
    console.log('6')
    resolve()
}).then(() => {
    console.log('7')
})
console.log('8')
输出:4 1 3 6 8 2 7 5

4、宏任务、微任务

JavaScript的事件分两种:宏任务(macro-task)、微任务(micro-task)
宏任务:包括整体代码scriptsetTimeoutsetInterval
微任务:Promise.then(非new Promise),process.nextTick(node中)
事件的执行顺序:先执行宏任务,然后执行微任务。

这个是基础,任务可以有同步任务和异步任务,同步的进入主线程,异步的进入Event Table并注册函数,异步事件完成后,会将回调函数放入Event Queue中(宏任务和微任务是不同的Event Queue),同步任务执行完成后,会从Event Queue中读取事件放入主线程执行,回调函数中可能还会包含不同的任务,因此会循环执行上述操作。

宏任务浏览器Node
I/O
setTimeout
setInterval
setImmediate
requestAnimationFrame
微任务浏览器Node
process.nextTick
MutationObserver
Promise.then catch finally

setTimeout(异步可以延时执行)

延时3秒:
setTimeout(() => {
    console.log('延时3秒');
},3000)
延时5、6秒:
function task(){
    console.log('task');
}
setTimeout(() => {
    task();
},3000)
console.log('执行console');
setTimeout总结:

经过指定时间后,把要执行的任务(本例中为task())加入到Event Queue中,又因为是单线程任务要一个一个执行,如果前面的任务需要的时间太久,那么只能等着,导致真正的延迟时间远远大于3秒。

setTimeout(fn,0)含义:

指定某个任务在主线程最早可得的空闲时间执行,意思就是不用再等多少秒了,只要主线程执行栈内的同步任务全部执行完成,栈为空就马上执行。

//代码1
console.log('先执行这里');
setTimeout(() => {
    console.log('执行啦')
},0);
输出:
先执行这里
执行啦

//代码2
console.log('先执行这里');
setTimeout(() => {
    console.log('执行啦')
},3000);
输出:
先执行这里
... 3s later
执行啦

5、 JS中EventLoop事件循环机制(即宏任务、微任务)

6、reduce方法

arr.reduce(callback,[initialValue])

为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。

callback (执行数组中每个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)
reduce用法如下:
(1)词频统计
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let nameNum = names.reduce((pre,cur)=>{
  if(cur in pre){
    pre[cur]++
  }else{
    pre[cur] = 1 
  }
  return pre
},{})
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}
(2)数组去重
let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((pre,cur)=>{
    if(!pre.includes(cur)){
      return pre.concat(cur)
    }else{
      return pre
    }
},[])
console.log(newArr);// [1, 2, 3, 4]
(3)二维数组转化为一维
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
    return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5]
(4)将多维数组转化为一维
let arr = [[0, 1], [2, 3], [4,[5,6,7]]]
const newArr = function(arr){
   return arr.reduce((pre,cur)=>pre.concat(Array.isArray(cur)?newArr(cur):cur),[])
}
console.log(newArr(arr)); //[0, 1, 2, 3, 4, 5, 6, 7]
(5)对象里的属性求和
var result = [
    {
        subject: 'math',
        score: 10
    },
    {
        subject: 'chinese',
        score: 20
    },
    {
        subject: 'english',
        score: 30
    }
];
var sum = result.reduce(function(prev, cur) {
    return cur.score + prev;
}, 0);
console.log(sum) //60

7、 手动实现Array.reduce()

Array.prototype.customReduce = function(fn , prev) {
    for(let i = 0; i<this.length; i++) {
        if (typeof prev === 'undefined') {
            // prev不存在
            prev = fn(this[i], this[i+1], i+1, this);
            i++;
        } else {
            prev = fn(prev, this[i], i, this);
        }
    }
    return prev;
}

8、手动实现bind()

bind介绍:创建一个新的函数, 当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

9、Js实现继承

(1)原型链
(2)借用构造函数
(3)原型链继承

10、this指向问题

11、ES6箭头函数

箭头函数用 => 符号来定义,相当于匿名函数。
(1)基本形式
let func = (num) => num;
let func = () => num;
let sum = (num1,num2) => num1 + num2;
[1,2,3].map(x => x * x);

12、js 实现一个前端路由 router

13、深拷贝、浅拷贝

总结:浅拷贝是拷贝一层,深层次的对象级别的就拷贝引用;深拷贝是拷贝多层,每一级别的数据都会拷贝出来。
具体来看,浅拷贝的时候如果数据是基本数据类型,那么就如同直接赋值,会拷贝其本身,如果除了基本数据类型之外还有一层对象,那么浅拷贝只能拷贝其引用,对象的改变会反应到拷贝对象上;但是深拷贝就会拷贝多层,即使是嵌套了对象,也会都拷贝出来。

浅拷贝
function simpleClone(initalObj) {
    var obj = {};
    for ( var i in initalObj) {
        obj[i] = initalObj[i];
    }
    return obj;
} 
var obj = {
    a: "hello",
    b:{
        a: "world",
        b: 21
    },
    c:["Bob", "Tom", "Jenny"],
    d:function() {
        alert("hello world");
    }
};
var cloneObj = simpleClone(obj);
console.log(cloneObj.a);//hello
console.log(cloneObj.b);//{a:'world',b:21}
console.log(cloneObj.c);//['Bob','Tom','Jenny']
console.log(cloneObj.d);//[Function:d]
 
//更改原对象中的a,b,c,d,看看拷贝过来的对象是否变化
cloneObj.a = "changed";
cloneObj.b.a = "changed";
cloneObj.b.b = 25;
cloneObj.c = [1, 2, 3];
cloneObj.d = function() { alert("changed"); };
console.log(obj.a);    //hello
console.log(obj.b);    //{a:"changed",b:25},只有对象是拷贝的引用类型
console.log(obj.c);    //['Bob','Tom','Jenny']
console.log(obj.d);    //[Function:d]
深拷贝(示例1)
var obj1 = { body: { a: 10 } };
var obj2 = { body: obj1.body };
obj2.body.a = 20;
console.log(obj1);
// { body: { a: 20 } } <-- 被改到了
console.log(obj2);
// { body: { a: 20 } }
console.log(obj1 === obj2);
// false
console.log(obj1.body === obj2.body);
// true
深拷贝(示例2 使用JSON转换)
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
详情戳链接!!!

14、ajax请求过程

Ajax 是一种异步请求数据的技术,可以改善用户的体验和程序性能。

(1)创建XMLHttpRequest对象,也就是创建一个异步调用对象;
(2)创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息;
(3)设置响应HTTP请求状态变化的函数;
(4)发送HTTP请求;
(5)获取异步调用返回的数据;
(6)使用JavaScriptDOM实现局部刷新。

var xmlHttp = new XMLHttpRequest();
xmlHttp.open('GET','demo.php','true');
xmlHttp.send()
xmlHttp.onreadystatechange = function(){
    if(xmlHttp.readyState === 4 & xmlHttp.status === 200){
    }
}
详情戳链接!!!

15、正则匹配手机

^:匹配目标字符串的开始位置
[abcd]:匹配到abcd中的任意一个字符
\d :匹配0-9的任意一个数字,相当于[0-9]
{n}:匹配前一项n次
$: 匹配目标字符串的结束位置
test:用于检测一个字符串是否匹配某个模式.

function checkPhone(phone){ 
    if(!(/^1[3456789]\d{9}$/.test(phone))){  
        return false; 
    } 
    return true;
}
console.log(checkPhone(12345678901))//false;

正则表达式总结 语法:/正则表达式主体/

16、跨域(1)(2)

16、 js数据类型、引用类型

六种数据类型(五种基本、一种复杂):NumberStringBooleanNullUndefinedObject(复杂)
三种引用类型:ObjectArrayFunction

17、 undefined、null、""、0值和false的区别总结

类型判断:

typeof(undefined)'undefined'
typeof(null)'object'
typeof("")'string'
typeof(0)'number'
typeof(false)'boolean'

转换为String:

String(undefined)"undefined"
String(null)"null"
String("")""
String(0)"0"
String(false)"false"

18、 New Object()和 {}区别

var a = {};
var b = new Object();
//从测试效果来看,{}快一点。

如果new Object()中没有传入参数,与{}是一样的;如果传入参数类型不同,会有不同的效果。

var Obj = function() {};
var a = {};
var b = new Object();
var c = new Obj();
// c最快,a次之,b最慢

二者与Object.create()的区别

19、 ES6新特性

(1)变量声明constlet

注:let 关键词声明的变量不具备变量提升(hoisting)特性;
let 和 const 声明只在最靠近的一个块中(花括号内)有效;
当使用常量 const 声明时,请使用大写变量,如:CAPITAL_CASING;
const 在声明时必须被赋值。

(2)模板字符串
// ES5
var a = 20;
var b = 30;
var string = a + "+" + b + "=" + (a + b);

//ES6  使用 ${} 来包裹一个变量或者一个表达式
const a = 20;
const b = 30;
const string = `${a}+${b}=${a+b}`; 
(3)箭头函数(Arrow Functions)

特点:不需要 function 关键字来创建函数;省略 return 关键字;继承当前上下文的 this 关键字。

// ES5
var add = function (a, b) {
    return a + b;
};
// ES6
var add = (a, b) => a + b;

// ES5
[1,2,3].map((function(x){
    return x + 1;
}).bind(this));
    
// ES6
[1,2,3].map(x => x + 1);
(4)函数参数的默认值
function add(x) {
    var x = x || 20;
    return x;
}
console.log(add(20)); //输出20
console.log(add(false)); //输出20

//打印结果是20,而不是fasle,结果并不是我们想要的;
//如果我们想要打印出false,就还要再做什么if判断等一些列操作.
//有了es6,可以很容易解决这个问题,如下:
function add(x = 20) {
    return x ;
}
console.log(add());//输出 20
console.log(add(false)); // 输出false
(5)二进制和八进制字面量

ES6 支持二进制和八进制的字面量,通过在数字前面添加 0o 或者0O 即可将其转换为八进制值:

let oValue = 0o10;
//或let oValue = 0O10;
console.log(oValue); // 8
 
let bValue = 0b10; // 二进制使用 `0b` 或者 `0B`
console.log(bValue); // 2
(6)对象和数组解构
// 对象
const student = {
    name: 'Sam',
    age: 22,
    sex: '男'
}

// ES5;
const name = student.name;
const age = student.age;
const sex = student.sex;
console.log(name + ' --- ' + age + ' --- ' + sex);

// ES6
const { name, age, sex } = student;
console.log(name + ' --- ' + age + ' --- ' + sex);
(7)对象超类

ES6 允许在对象中使用 super 方法

var parent = {
    foo() {
        console.log("Hello from the Parent");
    }
}
var child = {
    foo() {
        super.foo();
        console.log("Hello from the Child");
    }
}
Object.setPrototypeOf(child, parent);
child.foo(); 
// Hello from the Parent
 // Hello from the Child
(8)for...offor...in

for...of遍历数组的值。

let arr = ['a', 'b', 'c'];
arr.size = 3;
for (let i of arr) {
    console.log(i);
}

for...in遍历对象的属性。

let obj = {
	name: 'wuxiaodi',
	age: 18,
};
for (let i in obj) {
	console.log(i,obj[i])
}
(9)类Class

此处,Class不是新的对象继承模型,它只是原型链的语法糖表现形式。

//类中使用static关键词定义构造函数的的方法和属性:
class Student {
    constructor() {
        console.log("I'm a student.");
    }
    study() {
        console.log('study!');
    }
    static read() {
        console.log("Reading Now.");
    }
}
console.log(typeof Student); // function
let stu = new Student(); // "I'm a student."
stu.study(); // "study!"
Student.read(); // "Reading Now."
//类中的继承和超集
class Phone {
    constructor() {
        console.log("I'm a phone.");
    }
}
class MI extends Phone {
    constructor() {
        super();
        console.log("I'm a phone designed by xiaomi");
    }
}
let mi8 = new MI();
//I'm a phone.
//I'm a phone designed by xiaomi

20、 JS原型链、原型

21、 == 与 ===区别

总结:

==:先检查两个数数据类型,如果相同, 则进行===比较;如果不同, 则进行一次类型转换, 转换成相同类型后再进行比较。
===:如果类型不同,直接就是false.

a == b

(1)如果两个值类型相同,再进行三个等号(===)的比较
(2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:
    1)如果一个是null,一个是undefined,那么相等
    2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较

a === b

(1)如果类型不同,就一定不相等
(2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。
    (判断一个值是否是NaN,只能使用isNaN( ) 来判断)
(3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。
(4)如果两个值都是true,或是false,那么相等
(5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等
(6)如果两个值都是null,或是undefined,那么相等

22、 0.1+0.2!==0.3

0.1+0.2 === 0.3 //返回是false

JavaScript 中整数和浮点数都属于 Number 数据类型,所有数字都是以 64 位浮点数形式储存,即便整数也是如此。实际应该为: 0.1 + 0.2 = 0.30000000000000004
范ES6加入了一个新的东西–>Number.EPSILON。它表示 1 与大于 1 的最小浮点数之间的差,也就是 JavaScript 能够表示的最小精度。误差如果小于这个值,即不存在误差。
Number.EPSILON可以用来设置“能够接受的误差范围”。比如,误差范围设为 2 的-50 次方(即Number.EPSILON * Math.pow(2, 2)),即如果两个浮点数的差小于这个值,我们就认为这两个浮点数相等。

0.1 + 0.2 = 0.30000000000000004
0.1 + 0.2 - 0.3 = 5.551115123125783e-17
5.551115123125783e-17.toFixed(20) = '0.00000000000000005551'

如下:

function withinErrorMargin (left, right) {
    return Math.abs(left - right) < Number.EPSILON * Math.pow(2, 2);
}
var res = withinErrorMargin(0.1 + 0.2, 0.3);
console.log(res);//输出true

23、 const, var, let 的区别

const:定义的变量不可以修改,而且必须初始化。
const b = 2;//正确
// const b;//错误,必须初始化 
console.log('函数外const定义b:' + b);//有输出值
// b = 5;
// console.log('函数外修改const定义b:' + b);//无法输出 
var:定义的变量可以修改,如果不初始化会输出undefined,不会报错。
var a = 1;
// var a;//不会报错
console.log('函数外var定义a:' + a);//可以输出a=1
function change(){
    a = 4;
    console.log('函数内var定义a:' + a);//可以输出a=4
} 
change();
console.log('函数调用后var定义a为函数内部修改值:' + a);//可以输出a=4
let:块级作用域,函数内部使用let定义后,对函数外部无影响。
let c = 3;
console.log('函数外let定义c:' + c);//输出c=3
function change(){
    let c = 6;
    console.log('函数内let定义c:' + c);//输出c=6
} 
change();
console.log('函数调用后let定义c不受函数内部定义影响:' + c);//输出c=3

24、 call、apply、bind的区别

25、 闭包

闭包:指能够访问另一个函数作用域的变量的函数。简言之,闭包就是一个函数,这个函数能够访问其他函数的作用域中的变量。

// inner就是一个闭包函数,因为他能够访问到outer函数的作用域a
function outer() {
    var  a = '变量1'
    var  inner = function () {
           console.info(a)
    }
   return inner
}

《JavaScript高级编程》提到:由于闭包会携带包含它的函数的作用域,因为会比其他函数占用更多内容,过度使用闭包,会导致内存占用过多。

总结:闭包执行完后,其中使用的变量才会被销毁。
function outer() {
    var  a = '变量1'
    var  inner = function () {
           console.info(a)
    }
   return inner
}
var  inner = outer() //获得inner闭包函数
inner() //输出"变量1"

上述例子中,当程序执行完var inner = outer(),其实outer的执行环境并没有被销毁,因为他里面的变量a仍然被被inner的函数作用域链所引用,当程序执行完inner(), 这时候,inner和outer的执行环境才会被销毁调。

var a = 1;
function fn(){
    var b = 2;
    function fn1(){
        console.log(b);
    }
    fn1();//此时fn1环境及b都被销毁
}
fn();//输出2

上述例子中,随着fn1()执行完毕,fn1的执行环境被销毁,接着执行完fn(),fn的执行环境也会被销毁,只剩全局执行环境,现在没有b变量和fn1函数对象了,只有a 和 fn。

26、 数组和链表的优、缺点

数组

特点:

特点:
(1)在内存中,数组是一块连续的区域。 
(2)数组需要预留空间,在使用前要先申请占内存的大小,可能会浪费内存空间。 
(3)插入数据和删除数据效率低,插入数据时,这个位置后面的数据在内存中都要向后移。
(4)随机读取效率很高。因为数组是连续的,知道每一个数据的内存地址,可以直接找到给地址的数据。
(5)并且不利于扩展,数组定义的空间不够时要重新定义数组。

优点:
(1)随机访问性强
(2)查找速度快

缺点:
(1)插入和删除效率低
(2)可能浪费内存
(3)内存空间要求高,必须有足够的连续内存空间。
(4)数组大小固定,不能动态拓展

链表

特点:
(1)在内存中可以存在任何地方,不要求连续。 
(2)每一个数据都保存了下一个数据的内存地址,通过这个地址找到下一个数据。
     第一个人知道第二个人的座位号,第二个人知道第三个人的座位号。
(3)增加数据和删除数据很容易。 再来个人可以随便坐,比如来了个人要做到第三个位置,
    那他只需要把自己的位置告诉第二个人,然后问第二个人拿到原来第三个人的位置就行了。其他人都不用动。
(4)查找数据时效率低,因为不具有随机访问性,所以访问某个位置的数据都要从第一个数据开始访问,
    然后根据第一个数据保存的下一个数据的地址找到第二个数据,以此类推。 要找到第三个人,必须从第一个人开始问起。
(5)不指定大小,扩展方便。链表大小不用定义,数据随意增删。

优点:
(1)插入删除速度快
(2)内存利用率高,不会浪费内存
(3)大小没有固定,拓展很灵活。

缺点:
(1)不能随机查找,必须从第一个开始遍历,查找效率低

26、 java 、javascript的区别

(1)Java是SUN公司推出的新一代面向对象的程序设计语言,特别适合于Internet应用程序开发;
JavaScript是Netscape公司的产品,其目的是为了扩展Netscape Navigator功能,而开发的一种可以嵌入Web页面中的基于对象和事件驱动的解释性语言。
(2)JavaScript是基于对象的,而Java是面向对象的.
即Java是一种真正的面向对象的语言,即使是开发简单的程序,必须设计对象。
JavaScript是种脚本语言,它可以用来制作与网络无关的,与用户交互作用的复杂软件。它是一种基于对象和事件驱动的编程语言。
(3)在浏览器中所执行的方式不一样。
Java的源代码在传递到客户端执行之前,必须经过编译,因而客户端上必须具有相应平台上的仿真器或解释器;
JavaScript是一种解释性编程语言,其源代码在发往客户端执行之前不需经过编译。
(4)两种语言所采取的变量不一样。
Java采用强类型变量检查,即所有变量在编译之前必须作声明;
JavaScript中变量声明,采用其弱类型。
即变量在使用前不需作声明,而是解释器在运行时检查其数据类型。
(5)代码格式不一样。
Java是一种与HTML无关的格式,必须通过像HTML中引用外媒体那么进行装载,其代码以字节代码的形式保存在独立的文档中。
JavaScript的代码是一种文本字符格式,可以直接嵌入HTML文档中,并且可动态装载。编写HTML文档就像编辑文本文件一样方便。
(6)嵌入方式不一样。
在HTML文档中,JavaScript使用 <script>...</script> 来标识,而Java使用<applet> ... </applet>来标识。
(7)静态绑定和动态绑定。
Java采用静态联编,即Java的对象引用必须在编译时的进行,以使编译器能够实现强类型检查;
JavaScript采用动态联编,即JavaScript的对象引用在运行时进行检查,如不经编译则就无法实现对象引用的检查。

27、 JS中数组的增删改查

1、arr.push()   向数组末尾添加元素,返回的是添加后新数组的长度,原有数组改变
2、arr.unshift()  向数组开头添加元素,返回的是添加后新数组的长度,原有数组改变
    var arr=[1,2,3,4];
    var res=arr.unshift(6);
    console.log(res); ---->5   返回的是新数组的长度
3、arr.splice(n,m,x)从索引n开始删除m个元素,把新增的元素X放在索引n的前面,把删除的元素当成一个新数组返回,原有数组改变。
4、arr.splice(n,0,x)从索引n开始删除0个元素,把新增加的元素x放在索引n的前面,返回的是一个空数组,原有数组改变。
5、arr.splice(n,m)从索引n开始删除m个元素,把删除的内容当做新数组返回,原有数组改变
6、splice(0,0,x)----->unshift
1、arr.pop() 删除数组的最后一项,返回的是删除的那一项,原有数组改变
2、arr.shift() 删除数组的的第一项,返回的是删除的那一项,原有数组改变
    var arr=[5,8,3,4,6];
    var res=arr.shift();
    console.dir(res);---->5 返回数组第一项
3、删除数组最后一项的内容 arr.splice(arr.length-1,1)  //arr.length-1 数组最后一项的内容         arr.length-=1     arr.length--
    var arr=[5,8,3,4,6];
    arr.splice(arr.length-1,1);
    arr.length-=1;
    console.dir(arr);---->输出的是[5,8,3,4]
查询、复制、拼接
slice(n,m)从索引n开始,找到索引m处,把找到的内容作为新的数组返回,原有数组不改变        
slice(n-1,m)把数组的第n项到第m项提取出来
slice(n) 从索引n开始查找到数组末尾
slice(0) slice() 将原有数组复制一份 属于数组克隆  
concat() 也可以实现数组克隆   
concat的本意是实现数组的拼接 ary.concat(ary2) 把两个数组进行拼接
数组转化为字符串
tostring把数组的每一项拿出来用逗号隔开,原有数组不变
join("+")把数组的每一项拿出来用指定分隔符隔开
数组求和:
var ary=[5,8,3,4,6];
var str=ary.join("+");
var total=eval(str);
console.dir(total);  //将指定字符串变成真正的表达式执行
排列和排序
reverse() 把数组倒过来排序,原有数组改变
sort 可以实现由大到小或者由小到大的排序 但是直接写sort只能排序十以内的数字  
var arr = [1,3,5,2,6,3,4,1];
arr.sort(function(a,b){
    return (a-b);
})
console.log(arr);

28、 设计模式

29、 Nodejs作用

Angular面试题

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值