博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JavaScript 笔记02
阅读量:7081 次
发布时间:2019-06-28

本文共 6629 字,大约阅读时间需要 22 分钟。

JavaScript 笔记02

接笔记01

5.for / forEach / for-in / for-of

不多 bb,直接看代码。

// 循环数组let array = ['a', 'b', 'c'];// 普通 for 循环for (let index = 0; index < array.length; index++) {    const element = array[index];    console.log(element);}// forEach 循环// 不能使用 break 语句中断循环,也不能使用 return 语句返回到外层函数array.forEach(element => {    console.log(element);});// for-in 循环// 不推荐,因为这里的 index 不是数字,而是字符串,计算时用到很容易出错// 遍历出来后的顺序也可能随机for(const index in array) {     console.log(typeof index);    console.log(array[index]);}// for-of 循环// 这是最简洁、最直接的遍历数组元素的语法// 这个方法避开了for-in循环的所有缺陷// 与forEach()不同的是,它可以正确响应break、continue和return语句for (const value of array) {    console.log(value);}// 循环对象let me = {    name: 'ethan',    sex: 'male',    age: 24,    hobby: 'skate'};// for-in 循环for (const key in me) {    // 先判断是否含有该属性    if (me.hasOwnProperty(key)) {        console.log(key+ ':' + me[key]);    }}// for-of 循环,太麻烦,还不如 for-infor (const key of Object.keys(me)) {    console.log(key+ ':' + me[key]);}复制代码

但是 for-of 除了可以遍历数组和对象,它还可以遍历 string 字符串,以及 ES6 新增的 Map、Set 集合。更详细的可以参考。总结下,循环数组不需要 break 或者 return 推荐使用 forEach,需要的话使用 for-of,循环普通对象使用 for-in,剩下的都用 for-of,当然最重要的还是了解他们的异同,在使用的时候灵活选择。


6.关于函数参数

  1. js 中的函数不在乎参数的个数,也不在乎参数的类型
  2. js 中的参数其实是一个数组

关于上述两点,见如下代码

function abc (a, b) {    console.log(arguments[0]);    console.log(arguments.length);}abc(1);   // 1 1abc(1,2); // 1 2abc();    // undefined 0复制代码

再看下我们把函数的参数去掉

function abc () {    console.log(arguments[0]);    console.log(arguments.length);}abc(1);   // 1 1abc(1,2); // 1 2abc();    // undefined 0复制代码

结果是相同的。

可以利用 arguments 这个特性来写个不规定加数个数的加法

function add() {    if(arguments.length === 0){        return 0;    } else {        let total = 0;        for(let i = 0; i < arguments.length; i++) {            if (typeof arguments[i] === 'number') {                total += arguments[i];            }        }        return total;    }}console.log(add(1, 3, 5.5, 7, 8, 'a', 10));复制代码

有一点需要注意,arguments 实际上不是 array 的实例,而是一个 array 对象。

function abc() {    console.log(arguments);    console.log(typeof arguments);}abc();    // {}  objectabc(1);   // { '0': 1 }  objectabc(1,2); // { '0': 1, '1': 2 }  object复制代码

7.基本类型和引用类型复制值时的区别

这点主要是用来理解引用类型的指针

  • 复制基本类型的值时会在变量对象上创建一个新值,然后把这个新值复制到新变量分配的位置上。
  • 复制引用类型的值时,复制的其实是一个指针,虽然指针不同,但指针指向的是同一个对象,所以当其中一个引用类型改变了对象,另一个引用类型上的值也会变化。
let num1 = 1;let num2 = num1;console.log(num2); // 1num1 = 2;console.log(num2); // 1 ,由此可见,改变 num1 并不会影响 num2 的值复制代码
let person1 = {  name: 'ethan'};let person2 = person1;console.log(person2.name);  // ethanperson1.name = 'ethan1';console.log(person2.name); // ethan1,由此可见,改变 person1 会影响到 person2 的值,因为他们指向的是同一个对象。复制代码

8.检测类型

关于 typeof 在笔记1的第4点中已经写明,但 typeof 主要是用来检测基本数据类型,如果检测的值是一个对象或者 null,都会返回object,所以当变量是引用类型的时候,最好使用 instanceof,person instanceof RegExp,返回true/false。对于数组,还可以使用Array.isArray()


9.数组常用 API

方法 作用 返回值
push() 将任意数量的参数添加到数组末尾 修改后数组的长度
pop() 从数组末尾移除最后一项 移除的项
shift() 移除数组的第一项 移除的项
unshift() 将任意数量的参数添加到数字前端 修改后数组的长度
reverse() 反转数组项的顺序 反转后的数组
sort() 排序,默认的基本不用,需要重写 排序后的数组
concat() 基于当前数组创建一个新数组 新数组
splice() 删除:array.splice(0,2); 2个参数分别是要删除的第一项和要删除的项数 从原数组中删除的项组成的数组
插入:array.splice(2,0,"red","green");从第二项起删除0项,并插入 red 和 green。 从原数组中删除的项组成的数组
替换:array.splice(2,1,"red","green");参考上一条,很容易看懂 从原数组中删除的项组成的数组
indexOf() / lastIndexOf() 从数组开头/末尾开始查找位于第 n 位的项 查找的项
every() 对数组中的每一项运行给定函数 如果每一项都返回 true,则返回 true
filter() 对数组中的每一项运行给定函数 返回该数组中所有返回 true 的项组成的新数组
forEach() 对数组中的每一项运行给定函数 无返回值,该方法主要用来遍历数组
map() 对数组中的每一项运行给定函数 每次函数调用的结果组成的数组
some() 对数组中的每一项运行给定函数 只要有一项返回 true,则返回 true
reduce() /reduceRight() 归并方法,看下面的例子吧 看例子

重写 sort 方法

function compare (value1, value2) {  if(value1 < value2) {    return -1;  } else if (value1 > value2) {    return 1;  } else {    return 0;  }}let values = [14,2,53,3,6,1];values.sort(compare);console.log(values);  // [ 1, 2, 3, 6, 14, 53 ]复制代码

迭代方法

let num = [1,2,3,4,5,4,3,2,1];// every()let everyResult = num.every((item, index, array) => {  return (item > 2);});console.log(everyResult); // false// filter()let filterResult = num.filter((item, index, array) => {  return (item > 2)})console.log(filterResult); // [ 3, 4, 5, 4, 3 ]// forEach()num.forEach(element => {  console.log(element);  // 1  2  3  4  5  4  3  2  1});// map()let mapResult = num.map((item, index, array) => {  return (item*2);})console.log(mapResult);  // [ 2, 4, 6, 8, 10, 8, 6, 4, 2 ]// some()let someResult = num.some((item, index, array) => {  return (item > 2);})console.log(someResult);  // ture复制代码

reduce()

let num = [1,2,3,4,5];let sum = num.reduce((prev, cur, index, array) => {  return prev+cur;})console.log(sum);  // 15复制代码

10.关于 callee(严格模式下会报错)

函数内部有两个特殊的对象:arguments 和 this。callee 就是 arguments 的一个属性。

首先看下非常经典的阶乘函数。

function factorial(num) {  if (num <= 1) {    return 1;  } else {    return num * factorial(num-1);  }}console.log(factorial(5)); // 120复制代码

但这样有个问题,函数的执行和函数名factorial紧紧耦合在一起了,为了解决这个问题,我们就可以使用arguments.callee

function factorial(num) {  if (num <= 1) {    return 1;  } else {    return num * arguments.callee(num-1);  }}console.log(factorial(5)); // 120复制代码

这样,即使改了函数名也不会有任何影响。注意与 区分。


11.函数的 apply()、call() 和 bind()方法

  1. apply():接受两个参数:一个是在其中运行函数的作用域,另一个是参数数组。
function sum (num1, num2) {  return num1 + num2;}function applySum1 (num1,num2,num3) {  return sum.apply(this, [num1, num3]);}function applySum2 (num1,num2,num3) {  return sum.apply(this, arguments);}console.log(applySum1(10,20,30)); // 40console.log(applySum2(10,20,30)); // 30复制代码
  1. call():作用和apply()相同,不同的是第二个参数,不能以数组的形式,必须一个个列出来。
function sum (num1, num2) {  return num1 + num2;}function callSum1 (num1,num2,num3) {  return sum.call(this, num1, num3);}console.log(callSum1(10,20,30)); // 40复制代码

作用apply()call()最大的作用是能扩充函数赖以运行的作用域,如下:

window.color = 'red';let o = {  color: 'green'};function printColor () {  return this.color;}console.log(printColor.call(window)); // redconsole.log(printColor.call(this));   // redconsole.log(printColor.call(o));      // green复制代码
  1. 这个方法会创建一个函数的实例,其 this 值会被绑定到传给 bind()函数的值,如下:
let color = 'red';let o = {  color: 'green'};function printColor () {  console.log(this.color);}let objectPrintColor = printColor.bind(o);objectPrintColor(); // green复制代码

12.具体位数的小数处理

自己工作中刚好遇到,要求是四舍五入取小数点后一位。我是这样写的:

s = Math.round(s * 10) / 10 + 'km';复制代码

今天一看书中有现成的方法toFix()

let s = 3.1415;s1 = Math.round(s * 10) / 10;console.log(s1);         // 3.1console.log(typeof s1);  // numbers2 = s.toFixed(1);console.log(s2);         // 3.1console.log(typeof s2);  // string复制代码

似乎更简单,但数据类型已经改变了。所以书中也建议不要去实例化 Number 类型。当然,你看我工作中使用的场景,其实使用toFix()也不影响。


刚把JavaScript高级程序设计的 第五章看完,感觉周末并没有充分利用,还是有点贪玩的,下周可能会把多年前用的番茄工作法拿出来。希望下周能加快点,不过也不能一味追求速度,想这本书还有计划中的Java核心技术都得抓住重点,理解并尽量吃透,像 string 的 api 之类的就不用花太多心思,知道有哪些,分别是干嘛的就行了。笔记2就写到这吧,明天开始笔记3。

转载地址:http://ixjml.baihongyu.com/

你可能感兴趣的文章
2017-11-27 对中文语法的编程语言的质疑与回应
查看>>
高瓴资本向好未来注入5亿美元股权投资
查看>>
无人零售技术解决商云拿科技获A+轮融资,英特尔投资领投 ...
查看>>
三篇文章了解TiDB技术内幕-说存储
查看>>
联想创投子公司国民认证,助力农行全面升级FIDO移动生物识别安全认证 ...
查看>>
技术:搭建私有云kodexplorer
查看>>
Java 面试之技术框架
查看>>
SSM-配置
查看>>
【WiFi】让你的电脑成为无线路由器
查看>>
SQL SERVER 数据库备份
查看>>
日志服务IPython/Jupyter扩展实战:下载数据为Excel文件 ...
查看>>
IBM推出首款独立量子计算机,进一步推动量子计算商业化 ...
查看>>
设置通过Maven创建的工程的JDK版本—一劳永逸
查看>>
蚂蚁金服 SOFAArk 0.6.0 新特性介绍 | 模块化开发容器
查看>>
简单介绍我的开源小工具:SanicDB
查看>>
我做SAP CRM One Order redesign的一些心得体会
查看>>
Confluence 6 升级完成后的检查
查看>>
货拉拉完成D轮3亿美元融资,由高瓴资本、红杉资本领投
查看>>
第二十二章:动画(十)
查看>>
var,let和const深入解析(一)
查看>>