JS基础-2

141 阅读8分钟

数组

unshift && push

function mixedNumbers(arr) {
  // 只修改这一行下面的代码
  arr.unshift('I', 2, 'three');
  arr.push(7, 'VIII', 9)
  // 只修改这一行上面的代码
  return arr;
}
console.log(mixedNumbers(['IV', 5, 'six']));

pop && shift

用于删除元素的方法不接收参数,而且每次只能删除数组中的一个元素

splice

三个参数:索引+删除元素的个数+要添加的元素

第一个参数代表从数组中的哪个索引开始移除元素,

第二个参数表示要从数组中的这个位置开始删除多少个元素。

第三个参数可以是一个或多个元素,这些元素会被添加到数组中。

这样,我们能够便捷地将数组中的一个或多个连续元素换成其他的元素。

splice()不仅会修改调用该方法的数组(使得原始数组被修改),还会返回一个包含被移除元素的数组

slice

slice() 不会修改数组,而是会复制,或者说*提取(extract)*给定数量的元素到一个新数组。 slice() 只接收 2 个输入参数:第一个是开始提取元素的位置(索引),第二个是提取元素的结束位置(索引)。 提取的元素中不包括第二个参数所对应的元素。

使用展开运算符复制数组

slice()` 可以让我们从一个数组中选择一些元素来复制到新数组中,而 ES6 中又引入了一个简洁且可读性强的语法:展开运算符(spread operator),它能让我们方便地复制数组中的*所有*元素。 展开语法写出来是这样:`...

我们可以用展开运算符来复制数组:

let thisArray = [true, true, undefined, false, null];
let thatArray = [...thisArray];

indexOf

indexOf()方法接受一个元素作为输入参数,并返回该元素在数组中的位置(索引);若该元素不存在于数组中则返回-1

map

arr.map((item, index, arr)={//数组的成员,索引,数组本身
    return item.age;
});
console.log(item.age);

some

适用于从数组中找元素,找到元素时通过return true停止循环

  const arr = ["小红", "倪大红", "苏大强", "宝"];

  // forEach 循环一旦开始,无法在中间被停止
  /* arr.forEach((item, index) => {
  console.log('object');
  if (item === '苏大强') {
    console.log(index);
  }
}) */
arr.some((item, index) => {
    console.log('ok')
    if (item === '苏大强') {
    	console.log(index);
        // 在找到对应的项之后,可以通过 return true 固定的语法,来终止 some 循环
    	return true;
    }
}) 

every

返回值为布尔值,判断数组中的每一个元素是否都满足箭头函数体中的要求

arr.every(item=>{
	return item.state;
})
const arr = [
  { id: 1, name: '西瓜', state: true },
  { id: 2, name: '榴莲', state: false },
  { id: 3, name: '草莓', state: true },
]

// 需求:判断数组中,水果是否被全选了!
const result = arr.every(item => {
	return item.state===true   
})
console.log(result)

foreach

  1. 返回值为undefined

  2. arr1.foreach((item, index, arr)=>{
    	//回调函数:创建的函数不是由自己调用
    	console.log("item:"+item)
    	console.log("index:"+index)
    	console.log("arr:"+JSON.stringify(arr))
    })
    
  3. 当数组中的成员为基本数据类型时:foreach不会改变数组的值;当数组中的成员为对象时:可以通过修改对象的某个属性达到修改数组成员的目的

  4. 总结:纯粹的遍历数组时,可以使用foreach;但是,如果你想在遍历数组的同时,改变数组里的元素内容,那么最好使用map()方法

nums = [0, 1, 2, 3, 4],index = [0, 1, 2, 2, 1];
function creatArray(arr1, arr2){
    let targetArray = [];
    arr2.forEach((item, i) => {//item为arr2的元素,i为索引,每次自增1
        targetArray.splice(item, 0, arr1[i])
    });
    return targetArray;
}
console.log(creatArray(nums, index));
nums = [0, 1, 2, 3, 4],index = [0, 1, 2, 2, 1];
const creatArray = (arr1, arr2)=>{
    let res = arr2.reduce((pre, cur, i)=>{
        pre.splice(cur, 0, arr1[i]);
        return pre;
    }, [])
    let res2 = arr1.reduce((pre, cur, i)=>{
        pre.splice(arr2[i], 0, cur);
        return pre;
    }, [])
    return res;
}
console.log(creatArray(nums, index));

sort

arr1.sort((a,b)=>a-b)//升序排列
arr1.sort((a,b)=>b-a)//降序排列

根据对象属性的大小,对不同对象进行排序

filter

返回删除之后的数组

list.filter(item=>{
	return item.id !== id;
})

reduce

统计数组中元素的出现次数,以对象的形式返回

底层原理:回调函数,循环的是回调方法,数组中的每个成员都进入回调,每次回调方法返回的值都会传递到下次回调中

参数

Array.prototype.reduce((pre, cur, index, arr)=>{
	//pre为当前的返回值,每次循环都可以改变pre,最终返回pre
    //cur为数组中的元素,和index对应出现
    //arr为当前数组,这个参数很少用
}, InitValue)
//当不设置第二个参数时,将数组的第一个元素作为pre的初始值,并且从第二个元素开始循环。

返回值:第二个参数循环后的值

const countItem = (arr)=>{
    let res = arr.reduce((preArr, curItem)=>{
                            preArr[curItem] = preArr[curItem] ? preArr[curItem]+1 : 1;
                            return preArr;
                         },{});
    return res;
}
console.log(countItem(["apple","banana","orange","watermallean","apple","panana"]));
   

手写源码

arr = [1,2,3,4,5]
Array.prototype.reduceArr = function(fn, initValue){
    if (Object.prorotype.toString.call(fn)!=="[Object Function]"){
        throw new Error('current params is not correct');
    }
    let arr = this; 
    let initIndex; 
    let acc; 
    initIndex = arguments.length === 1 ? 1 : 0;
    acc = arguments.length === 1 ? arr[0] : init;
    for (let i = initIndex; i < arr.length; i++) {
        acc = fn(acc, arr[i], i, arr)
    }
    return acc;
}
let res = arr.reduce((pre, cur)=>{
    return pre+cur;
}, 10)
console.log(res);

数硬币问题

arr = [1,2,3,4,5]
const count = (arr) => {
    let res = arr.reduce((pre ,curItem)=>{
        return pre+(curItem%2!==0?(Math.floor(curItem/2)+1):curItem/2);
    }, 0);
    return res;
}
console.log(count(arr));

数组降维

递归+reduce

nums = [0, 1, 2, 3, [4, 12], [1,[23, 90, [100,1]]]];
const flatten = arr => {
    let res = arr.reduce((pre, cur)=>{
        return pre.concat(Array.isArray(cur)?flatten(cur):cur);
    }, [])
    return res;
}
console.log(flatten(nums));

正则表达式

验证邮箱

var email = "2253541907@qq.com";
var reg = /^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]+)+$/
if(reg.test(email)){
    console.log("邮箱格式正确");
}
else{
    console.log("邮箱格式错误,请检查后重新输入")
}

替换字符串

string_item.replace(reg, "替换后的字符串")
var str = "12adsf5453 frter }sadas342"
console.log(str)
var reg = /[a-zA-Z \}]/g
var newStr = str.replace(reg, "") 

ES6

要点

  1. let代替var
  2. 块级作用域
  3. 不存在变量提升与重复声明
  4. 重要的是要了解使用 const 生命的变量, 其包含的对象(包括数组和函数)仍然是可变的。 使用 const 声明变量只是防止了变量标识符的重新分配

模板字符串

支持换行,便捷的文本拼接

支持解构赋值

数组的解构赋值

let [n,m] = [10,20]
[n,m] = [m,n]

对象的解构赋值

let {name, age} = {name:"xiaoming", age:22}

通过解构赋值传递参数

const profileUpdate = (profileData) => {
  const { name, age, nationality, location } = profileData;
}
const profileUpdate = ({ name, age, nationality, location }) => {
	/*对解构后的变量进行处理*/
    return something;
}

简单属性对象的语法

const createPerson = (name, age, gender) => {

 const obj = ({name,age,gender});

 return obj;

};

const obj1 = createPerson("zhudi",16,1);
//返回{
      name:"zhudi",
      age:16,
      gender:1
}

语法糖

作用:避免重复造轮子

导入部分内容

import {函数名1,函数名2,...} from './my_functions.js'

导入全部内容

假设你有一个文件,你希望将其所有内容导入到当前文件中。 可以用 import * as 语法来实现。 下面是一个从同目录下的 math_functions.js 文件中导入所有内容的例子:

import * as myMathModule from "./math_functions.js";

上面的 import 语句会创建一个叫作 myMathModule 的对象。 这只是一个变量名,可以随便命名。 对象包含 math_functions.js 文件里的所有导出,可以像访问对象的属性那样访问里面的函数。 下面是使用导入的 addsubtract 函数的例子:

myMathModule.add(2,3);
myMathModule.subtract(5,3);

默认导入与默认导出

在上一个挑战里,学习了 export default 的用法。 还需要一种 import 的语法来导入默认的导出。 在下面的例子里,addmath_functions.js 文件的默认导出。 以下是如何导入它:

import add from "./math_functions.js";

这个语法有一处特别的地方, 被导入的 add 值没有被花括号({})所包围。 add 只是一个变量的名字,对应 math_functions.js 文件的任何默认导出值。 在导入默认导出时,可以使用任何名字。

函数进阶

闭包

暂无

箭头函数

基本语法

const fun = (x) => {
	return x*x;
}
const fun = (x) => x*x;
let result = fun(2)
console.log(result)

this指向不同

  1. 箭头函数和普通函数的this指向不同:箭头函数的this指向上层作用域
  2. 普通函数指向的是调用该函数的对象,例如setInterval指向的windows对象
  3. 对于箭头函数:在哪里定义,this就指向谁,例如此时的函数是在cat对象内部定义,所以此时的this指向cat对象
const cat = {
	name:"huanhuan",
	sayName(){
		let self = this;
		windows.setInterval(function(){
			console.log(self.name)
		}, 1000)
	}	
}
cat.sayName()
const cat = {
	name:"huanhuan",
	sayName(){		 
		setInterval( ()=>console.log(this.name), 1000)
	} 
}
cat.sayName()

面向对象

// 只修改这一行下面的代码
class Thermostat {
  constructor(fahrenheit) {
    this.fahrenheit = fahrenheit;
  }
  
  get temperature() {
    return (5 / 9) * (this.fahrenheit - 32);
  }
  
  set temperature(celsius) {
    this.fahrenheit = (celsius * 9.0) / 5 + 32;
  }
}
// 只修改这一行上面的代码

const thermos = new Thermostat(76); // 设置为华氏刻度
let temp = thermos.temperature; // 24.44 摄氏度
thermos.temperature = 26;
temp = thermos.temperature; // 26 摄氏度

异步

then和catch

当程序需要花费未知的时间才能完成时(比如一些异步操作,一般是服务器请求),promise 很有用。服务器请求会花费一些时间,当结束时,需要根据服务器的响应执行一些操作。 这可以用 then 方法来实现,

then

当 promise 完成 resolve 即promise成功时会触发 then 方法。语法如下:

myPromise.then(result => {

});

result 即传入 resolve 方法的参数。

catch

当 promise 失败时会调用 catch 方法。 当 promise 的 reject 方法执行时会直接调用。 用法如下:

myPromise.catch(error => {

});

error 是传入 reject 方法的参数。

const makeServerRequest = new Promise((resolve, reject) => {
  // responseFromServer 设置为 true,表示从服务器获得有效响应
  let responseFromServer = true;//此处在实际应用中应该为对服务器的具体操作

  if(responseFromServer) {//判断有无响应
    resolve("We got the data");
  } else {  
    reject("Data not received");
  }
});
makeServerRequest.then(result=>{//若有响应则执行promise对象的then函数
  console.log(result);
});
makeServerRequest.catch(error => {
  console.log(error);
});