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)
宏任务:包括整体代码script
,setTimeout
,setInterval
微任务: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)使用JavaScript
和DOM
实现局部刷新。
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数据类型、引用类型
六种数据类型(五种基本、一种复杂):Number
、String
、Boolean
、Null
、Undefined
、Object
(复杂)
三种引用类型:Object
、Array
、Function
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最慢
19、 ES6新特性
(1)变量声明const
和let
注: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...of
和 for...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);