持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情
在js中, 函数也是对象, 是一种特殊的对象, 具备普通对象的所有功能, 例如: 属性
区别于普通对象的是, 函数可以封装一段代码, 在需要的时候, 可以通过调用函数来执行这段代码
创建函数
创建函数有两种方式
第一种函数声明方式
function 函数名([形参1, 形参2, ...]) {
// 函数体
}
第二咱函数表达式方式
对于该方式, 变量名就是函数名
let/var 变量名 = function([形参1, 形参2, ...]) {
// 函数体
}
// 定义函数
function func1() {
console.log('这是一个函数');
}
let func2 = function() {
console.log('这也是一个函数');
}
调用函数
函数名();
// 调用函数
func1();
func2();
形参和实参
在定义函数, 声明函数体可以使用这几个变量, 对于形参的值, 在调用时都会知道
在调用函数时, 传入具体的实参, 传入的这些实参会相应的赋值给对应的形参
在js中, 在调用函数时, 不会检查实参的类型和个数是否和该函数的形参的类型和个数匹配
如果实参的个数大于形参的个数, 多余的实参将不会使用
如果实参的个数小于形参的个数, 那么没有赋值的形参是undefined
function func3(x, y) {
console.log('' + x + ',' + y);
}
let = 1, b = 2, c = 3;
func3(a) // 1,undefined
func3(a, b, c) // 1,2
typeof 函数名
该运算符操作的是函数名的话则返回function
console.log(typeof func3); // function
函数的返回值
使用return语句来返回函数的返回值, 当当执行完return语句函数立即退出
- 如果函数没有return语句, 或者return;是这样的return语句, 则相当于return undefined;
- 函数的返回值可以是做任意类型, 可以是基本类型, 可以是对象, 也可以是函数
function func4() {
console.log('这是一个没有return语句的函数');
}
function func5() {
console.log('这是一个有return语句的函数');
return;
console.log('这是一个有return语句后面的语句');
}
// 返回值为基本类型的函数
function func6(a, b) {
return a + b
}
// 返回值为对象类型的函数
function func7() {
return {
name: 'shaosiming',
age: 18
}
}
// 返回值为函数类型的函数
function func8() {
return function(a, b) {
return a * b
}
}
console.log(func4()); // undefined
console.log(func5()); // undefined
console.log(func6(3, 5)); // 8
console.log(func7()); // {name: 'shaosiming', age: 18}
console.log(func8()); // 一个函数
全局作用域
在script标签中的代码都属于全局作用域代码
在全局作用域中有一个window对象, 代表的是当前页岩的浏览器窗口
在全局作用域中创建的变量会作为属性保存在window对象中
在全局作用域中创建的函数会任务方法保存在window对象中
在全局作用域中的变量和函数, 在任意位置都可以访问, 如: 在函数的作用域中可以访问全局作用域中的变量
// 直接访问window对象
console.log(window);
// 全局作用域中的变量
var a = 3
// 在函数作用域中访问全局变量
// 在函数中访问window对象
function func() {
console.log('func: ' + a);
console.log("func: " + window);
}
func()
// 我们还可以这样访问全局作用域中的变量和函数
console.log(window.a);
window.func()
函数作用域
函数的作用域, 每次执行创建, 执行完毕销毁, 因此每次调用函数都会创建一个新的作用域
在全局中创建的变量可以在函数中访问, 而在函数中创建的变量,不能在全局中访问
在函数中访问变量时的查找规则, 先在函数作用域中查找变量, 如果没有找到则往上寻找, 直到寻找到全局作用域, 如果在全局作用域中没有找到则是undefined
let b = 3
let c = 5
function func2() {
let b = 5
console.log('func2: ' + b); // 在函数作用域中就可以查找到变量b, 因此输出5
console.log('func2: ' + c); // 在函数作用域中找不到, 往上查找, 在全局作用域中找到c, 因此输出4
}
func2()
console.log('global: ' + b); // 3
变量的提前声明
在全局作用域中和函数作用域中, var声明的变量会在所有代码执行前被声明, 但不会被赋值
因此我们可以在变量定义前使用变量
console.log('global b: ' + b); // undefined
var b = 3;
function func3() {
// console.log('func3: ' + a); // undefined
// var a = 3; // 可以这样使用
a = 3; // error: a is not defined
}
func3()
函数的提前声明
在全局作用域和函数作用域中, 使用function 函数名() {} 创建的函数, 会在所有代码执行前被创建, 因此我们可以在函数定义前调用函数, 但是var 函数名 = function() {}则不行
func4(); // func4
func5(); // eroro funct is not a function
function func4() {
console.log('func4');
}
var func5 = function() {
console.log('func4');
}
函数对象的call和apply方法
在进行函数调用的时候我们不但可以使用 函数名(); 这种方式调用
还可以使用 函数名.call(); 和 函数名.apply()进行调用
使用这两个方法来调用函数的时候, 可以指定函数中的this对象
在使用call方法是, 可以直接传实参. 而在使用apply方法, 需要将实参放入数组中, 再进行传递
function func() {
console.log('func:' + this);
}
func(); // this: 在这个函数中this是window对象
func.call(); // this: window对象
let person = {name: 'shaosiming', age: 18};
func.call(person); // this指向person
func.apply(person); // this指向person
函数对象的arguments属性
该属性存放着在调用函数时传递过来的实参
可以使用下标来获取参数
arguments.callee用来表示当前执行的函数对象
function func() {
console.log('func:' + this);
console.log('args: ' + arguments[0] + ', ' + arguments[1] + ', ' + arguments[2]);
console.log(arguments.callee); // 就是当前函数func
}
func.call(person, 1, 2);
func.apply(person, [1, 2]);