文章目录
重新巩固JS系列,都是比较基础的东西,可以进行查漏补缺,很快看完,这是第四篇。
其他JS重新巩固系列:
1. 函数概述
在编程领域中,子程序是一个大型程序中的某部分代码,由一个或多个语句块组成。它负责完成某项特定任务,而且相较于其他代码,具备相对的独立性。一般会有输入参数并有返回值,提供对过程的封装和细节的隐藏。不同语言中,子程序的叫法:
在JS中,子程序成为函数(function)。如果函数挂载在一个对象上,就称它为对象的方法。例子:
// 两数求和函数
function sum(numA, numB) {
return numA + numB;
}
// 对象的方法
const person = {
//person对象的方法
getName: function() {
return this.name;
}
}
JS中,函数也是对象,程序可以随意操控它们,比如赋值给变量、作为参数传递给其他函数、可以给它们设置属性和方法。
2. 函数定义
使用关键字 function定义,通常有2种方式: 函数声明语句和函数表达式。
// 函数声明语句: sum为函数名,numA、num为形参。
function sum(numA, numB) {
return numA + numB;
}
// 函数表达式
const sum = function(numA, numB) {
return numA + numB;
}
函数返回值使用return关键字, 没有return语句则默认返回undefined。
第三种定义的方式是使用Function构造函数。最后一个参数是函数体,之前的都是函数的形参。
const sum = new Function('numA', 'numB', 'return numA + numB');
备注:一般不使用Function构造函数的形式(使用的场景:比如将一段字符串转化为可执行的代码时)。
3. 函数调用
函数名称加一对括号就可以调用函数。括号中可以传入实参,和形参一一对应。
function sum(sumA, sumB) {
return numA + numB;
}
const result = sum(1, 2);
console.log(result); // 3
4. 函数参数
定义函数时,形参不需要指定类型,调用函数时也不会检查实参的类型和个数。
function sum() {
return '?';
}
const result = sum(1, 2);
console.log(result); // 正常执行,输出:?
4.1 默认值
函数参数可以指定默认值,如果调用时没有传入对应的值,则会使用默认值。
function sum(numA, numB = 2) {
return numA + numB;
}
console.log(sum(1)); // 3
4.2 剩余参数
ES6新增:如果函数的最后一个命名参数以...
为前缀,则它是包含剩余参数的数组。
function sum(numA, ...nums) {
if (nums) {
for(let i = 0; i < nums.length; i++) {
numA += nums[i]
}
}
return numA;
}
console.log(sum(1)); // 1
console.log(sum(1, 2, 3)); // 6
5. 函数内部属性
在函数内部,有2个特殊对象: arguments 和 this。
5.1 arguments对象
在函数体内,arguments表示实参列表对象,它是一个类数组对象(类数组中的“类”字表示像的意思,就是说arguments对象像数组),可以通过下标访问对应的实参值,也有length属性,但是没有数组的一些方法。
function sum() {
return arguments[0] + arguments[1];
}
console.log(sum(1, 2)); // 3
5.2 this对象
在函数体内,this是指函数执行的环境对象(也叫context,即函数上下文)。一般来说,this指向调用函数的对象,如果没有,就是全局对象,在浏览器中即为Window对象(Node环境中为Global对象)。
const sum = function () {
console.log(this);
}
// 严格模式下是 undefined, 非严格模式下是 Window(Node环境为Global)
sum();
const obj = {
sum: function () {
console.log(this);
}
};
// this 为 obj 对象
obj.sum();
6. 函数是特殊对象
函数是特殊的对象,意味着它也是一种值。所以函数可以: 当作参数传递、赋值给变量、作为数组的元素中等。
function callSomeFunction (func, arg) {
return func(arg);
}
function sum(sum) {
return 1 + sum;
}
console.log(callSomeFunction(sum, 2)); // 3
函数具有的属性:length 和 name。 方法: call、apply、bind。
6.1 函数的属性:length 和 name
6.1.1 length属性
函数的length是该函数期望参数的个数(第一个有默认参数前的参数),不包括有默认值参数和剩余参数。
function sum(numA, numB = 1, ...nums) { }
console.log(sum.length); // 1
function sum(numA, numB = 1, numC, ...nums) { }
console.log(sum.length); // 1
6.1.2 name属性
函数的name属性是该函数的名称。
const sum1 = function () {}
const obj = {
sum2: function () {}
}
const sum3 = new Function();
console.log(sum1.name); // sum1
console.log(obj.sum2.name); // sum2
console.log(sum3.name); // anonymous
6.2 函数的方法: call、apply、bind
6.2.1 call方法
调用函数,可以指定函数中this和传入参数列表。
const obj = {
name: 'cc',
say: function (content) {
const speak = function () {
console.log(`${this.name} say ${content}`)
};
speak();
}
};
obj.say('welcome'); // say welcome
以上示例中,在say方法中调用speak,由于speak方法是直接单独调用的,所以函数体内的this指向的是全局变量window,而全局变量window的name属性值为空(''
),所以输出'' say welcome
。
提问:①函数speak中的this.name如何取到cc这个值? ②函数speak如何接收更多参数?
解决方法:
① speak() -----> speak.call(this) ,即可。
② speak() -----> speak.call(this, ‘one’, ‘two’) ,在call函数第一个参数后面依次添加参数即可。
6.2.2 apply方法
调用函数,可以指定函数中的 this 和传入 参数数组 ,作用其实和call方法一样,只是后面的参数是以数组的形式传入。助记方法: apply----->首字母a,数组array的首字母也是a------->apply方法传参是以数组的形式。
6.2.3 bind方法
生成一个新的函数,可以指定函数调用时的this对象和传入参数列表。
6.2.1中同样的两个问题的解法:
① 因为bind方法是生成一个新的方法,我们需要再调用这个新方法才能得到执行结果:
const obj = {
name: 'cc',
say: function (content) {
const speak = function () {
console.log(`${this.name} say ${content}`)
};
const speak1 = speak.bind(this);
speak1()
}
};
obj.say('welcome'); // cc say welcome
② 传参的话,直接在bind函数中的第一个参数后面以参数列表的形式传入即可。
const speak1 = speak.bind(this, 'one', 'two')
7. 变量作用域简介
JS引擎查找变量的过程,从局部作用域向外层查找,一直到全局作用域为止。
局部变量的名字可以和全局变量相同,但两者互不影响。
const name = 'cc1';
function outerFunc() {
const name = 'cc2';
function innerFunc() {
const name = 'cc3';
console.log(name); // 'cc3'
}
innerFunc()
console.log(name); // 'cc2'
}
outerFunc();
console.log(name); // 'cc1'
ES6块级作用域:ES6引入了let
、const
,它们声明的是块级作用域变量,块由{...}
构成。
let x = 10;
var y = 10;
{
let x = 5;
var y = 5;
{
let x = 2;
var y = 2;
console.log(x, y) // 2 2
}
console.log(x, y) // 5 2
}
console.log(x, y) // 10 2
原型相关感兴趣的可以看看这篇文章:帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
8. 箭头函数(arrow function)
箭头函数表达式的语法比函数表达式更短,并且不绑定自己的this、arguments、super或new.target。这些函数表达式最适合用于非方法函数,并且它们不能用作构造函数。
const materials = ['Hydrogen', 'Helium', 'Lithium', 'Beryllium'];
materials.map(function (material) {
return material.length;
}); // [8, 6, 7, 9]
materials.map((material) => {
return material.length;
}); // [8, 6, 7, 9]
materials.map(material => material.length ); // [8, 6, 7, 9]
若对你有帮助,可以支持一下作者创作更多好文章哦~