文章目录
理解 JS 函数
JS 函数不仅仅是一个普通函数。与其他编程语言不同,函数可以赋值给变量,可以作为参数传递给另一个函数,也可以从另一个函数中返回。
console.log(square(5));
/* ... */
function square(n) { return n * n; }
console.log(square(5));
var square = function(n) {
return n * n;
}
//上述代码会报错,square未定义
在 JS 中,如果将函数定义为变量,这函数名将被挂起,只有当 JS 执行到它的定义位置时才能访问到
bind, apply 和 call 的用法
当希望延迟调用带有特定上下文的函数时,使用 .bind(),这在事件中很有用。当希望立刻调用函数时,使用 .call() 或 .apply(),同时会修改上下文。
call 函数接收了两个参数:
- 上下文
- 函数参数
上下文是在函数体内替换 this 的对象。接着,参数会通过函数的参数传入。例如:
var cylinder = {
pi: 3.14,
volume: function(r, h) {
return this.pi * r * r * h;
}
};
call 是这样用的:
cylinder.volume.call({pi: 3.14159}, 2, 6);
75.39815999999999
Apply 是完全相同的用法,只是函数参数是以列表的形式传递。
cylinder.volume.apply({pi: 3.14159}, [2, 6]);
75.39815999999999
Bind 将一个全新的 this 赋给指定的函数。Bind 与 call 或 apply 不同,bind 情况下,函数不会立即执行。
它提供了给函数传入上下文的方法,并返回带有更新的上下文的函数。
这意味着 this 变量就是用户提供的变量。这在处理 JavaScript 事件时非常有用。
JavaScript 作用域
作用域分为三种:
- 全局作用域
- 当前作用域/函数作用域
- 块级作用域(ES6 中有介绍)
全局作用域是我们常用的:
x = 10;
function Foo() {
console.log(x); // Prints 10
}
Foo()
当你在当前函数定义一个变量,函数作用域就出现了:
pi = 3.14;
function circumference(radius) {
pi = 3.14159;
console.log(2 * pi * radius); // Prints "12.56636" not "12.56"
}
circumference(2);
ES6 标准引入了新的块级作用域,块级作用域将变量的作用范围限制在特定的括号内。
var a = 10;
function Foo() {
if (true) {
let a = 4;
}
alert(a); // alerts '10' because the 'let' keyword
}
Foo();
this 关键词(全局,函数和对象范围)
如果是在浏览器上运行,全局上下文指的是 Window 对象。这意味着,打开浏览器的控制台并输入下面的内容,按下回车键,它会返回 true。
this === window;
当程序的上下文和作用域发生了改变,this 的指向也跟着改变。现在看看当前上下文的 this:
function Foo(){
console.log(this.a);
}
var food = {a: "Magical this"};
Foo.call(food); // food is this
无论父级作用域是什么,子级都会继承父级作用域。
正则表达式
我们可以通过以下方法创建一个新的正则表达式:
var re = /ar/;
var re = new RegExp('ar'); // This too works
上面的正则表达式表示与给定字符串匹配的表达式。一旦定义了一个正则表达式,我们可以尝试匹配和查看符合条件的字符串。我们可以使用exec函数来匹配字符串。
re.exec("car"); // returns ["ar", index: 1, input: "car"]
re.exec("cab"); // returns null
正则表达式包含许多类型的元素。其中一些是:
- 字符:w-查找单词字符,d-查找数字,D-查找非数字字符
- 字符类:[x-y]查找从x到y到字符,[^x]查找非x的任何字符
- 量词:+,?,*(查找多个或0个匹配字符)
- 边界:^(开头),$(结尾)
除了 exec 函数,还有 match, search 和 replace 函数,它们可通过正则表达式找到某个字符串。但这些函数应该应用于字符串本身
Map, Reduce 和 Filter
map
map 函数用在 JavaScript 数组中。map 函数通过将数组的每个元素传递给转换函数,并返回一个新数组。JS 数组中 map 的一般语法是:
arr.map((elem){
process(elem)
return processedValue
}) // returns new array with each element processed
假设,我们最近正在处理串行键中少量不需要的字符。我们需要把它们移走。我们不是通过循环和查找来移除字符,而是使用map达到相同的效果并获得结果数组。
var data = ["2345-34r", "2e345-211", "543-67i4", "346-598"];
var re = /[a-z A-Z]/;
var cleanedData = data.map((elem) => {return elem.replace(re, "")});
console.log(cleanedData); // ["2345-34", "2345-211", "543-674", "346-598"]
map 携带一个函数参数。而该函数自身也带有参数。这个参数是从数组中筛选的。这个方法应用于数组中的所有元素,并返回处理过的元素。
reduce
ruduce 函数将指定的列表缩减为一个最终值。当然,通过循环数组并将结果保存在变量中也能实现相同的效果。但在这里,同样是将一个数组缩减成一个值,reduce 更为简洁。JS 中 reduce 的一般语法是:
arr.reduce((accumulator,
currentValue,
currentIndex) => {
process(accumulator, currentValue)
return intermediateValue/finalValue
}, initialAccumulatorValue) // returns reduced value
accumulator 保存中间值和最终值。currentIndex, currentValue 分别是当前数组元素的索引和值。initialAccumultorValue 是传递给函数的初始值。
reduce 的一个实际用途是合并数组中的数组元素。合并是将内部数组元素转换成一个简单数组。例如:
var arr = [[1, 2], [3, 4], [5, 6]];
var flattenedArray = [1, 2, 3, 4, 5, 6];
也可以通过常规迭代来实现这一点。但使用 reduce 一行代码就搞定了。
var flattenedArray = arr.reduce((accumulator, currentValue) => {
return accumulator.concat(currentValue);
}, []); // returns [1, 2, 3, 4, 5, 6]
filter
filter 也是处理数组中的每个元素并最终返回另一个数组(而不像 reduce 返回一个值)。筛选后的数组长度可以小于或等于原始数组。因为相对于输出数组,传入的筛选条件不可能是极少/0。JS filter 的一般语法是:
arr.filter((elem) => {
return true/false
})
这里的 elem 是数组的数据元素,而函数返回的 true/false 将表示包含/不包含被过滤元素。常见的例子是根据给定的开头和结尾条件筛选单词数组。假设要筛选一个以 t 开头且以 r 结尾的单词数组。
var words = ["tiger", "toast", "boat", "tumor", "track", "bridge"]
var newData = words.filter((elem) => {
return elem.startsWith('t') && elem.endsWith('r') ? true:false;
}); // returns ["tiger", "tumor"]
思维导图
JS基本概念
JS基本语句
JS编程风格
JS操作符
JS数组用法
JS字符串用法
编程实践
Date 用法
鸣谢
思维导图鸣谢:
GitHub:lidaguang