写在前面
本文是我通过在网易云课堂上学习 叶建华 老师的 撩课-零基础玩转JavaScript 视频教程,整理、精炼其配套笔记总结而来的。附上视频教程地址:
https://study.163.com/course/courseMain.htm?courseId=1005973001
以下是我的所有js入门笔记
JavaScript入门笔记1:https://www.jianshu.com/p/ab044eb35c56
JavaScript入门笔记2:https://www.jianshu.com/p/348805d50b77
JavaScript入门笔记3:https://www.jianshu.com/p/2146931d6706
JavaScript入门笔记4:https://www.jianshu.com/p/e95f00b53343
JavaScript入门笔记5:https://www.jianshu.com/p/97a241434881
JavaScript入门笔记6:https://www.jianshu.com/p/fc091ce8924e
JavaScript入门笔记7:https://www.jianshu.com/p/ea33bfb83da1
本章节内容
1、函数
---1.1、 定义
---1.2、常见声明方式
---1.3、arguments对象
---1.4、return
---1.5、对比“函数式声明方式”和“函数表达式声明方式”
---1.6、匿名函数
---1.7、函数是一种数据类型
---1.8、回调函数
---1.9、变量的作用域
1、函数
1.1、 定义
- 函数就是可以重复执行的完成特定功能的一段代码块
- 函数也是一个对象
- 使用typeof检查一个函数对象时,会返回function
1.2、常见声明方式
(1)函数声明方式
// num1,num2是形式参数
function add(num1,num2){
return num1+num2;
}
(2) 函数表达式声明方式
// num1,num2是形式参数
var add= function(num1,num2){
return num1+num2;
};
(3)使用Function构造函数
不推荐使用, 主要用于面向对象时理解"函数就是对象, 函数名就是指针"这一概念
// num1,num2是形式参数
var add = new Function('num1','num2','return num1+num2');
函数调用
var add= function(num1,num2){
return num1+num2;
};
var a = 1, b = 2;
// 调用函数,a和b是实际参数
var result = add(a, b);
console.log(result); // 3
函数使用注意
- 注意形参和实参的区别
- 函数的实参可以是任意的数据类型
- 调用函数时,解析器不会检查实参的数量, 多余实参不会被赋值, 如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined
1.3、arguments对象
- arguments对象仅仅属于函数。
- arguments是一个伪数组对象。
- 里面包含一个叫callee的指针,这个指针指向arguments所在的函数对象。
- 里面还包含传入该函数的所有实际参数。
function sum(num1, num2){
console.log(arguments);
}
sum(100, 200);
arguments对象的一些应用实例
(1)比较形参个数和实参个数是否相等
arguments.length 返回实参个数
函数名.length 返回形参个数
function sum(num1, num2){
console.log(arguments.length === sum.length);
}
sum(100, 200); // true
sum(100, 200, 300); //false
(2)arguments方便函数取出实参用于遍历运算
function sum(){
var value = 0;
for(var i = 0; i < arguments.length; i++){
value += arguments[i];
}
consolelog(value);
}
sum(10, 20, 30);
1.4、return
function getMin() {
var minValue = arguments[0];
for(var i = 0; i < arguments.length; i++) {
if(arguments[i] < minValue){
minValue = arguments[i];
}
}
return minValue;
}
var minValue = getMin(10, 20, -30);
console.log(minValue); // -30
1.5、对比“函数式声明方式”和“函数表达式声明方式”
函数式声明方式
- JavaScript解析器首先会把当前作用域的函数声明提前到整个作用域的最前面。可以函数调用在前,函数声明在后。
- 函数声明方式,必须紧跟在function后设置函数名。
result = func(6, 7);
console.log(result); // 13
function func(a, b) {
return a + b;
}
函数表达式声明方式
- 函数表达式声明方式,相当于先声明变量var sum = undefined,直到执行到了var sum = function()语句,sum这个函数方法才能被调用。不能函数调用在前,函数声明在后。
- 函数表达式声明方式,不必紧跟在function后设置函数名,函数名由变量名决定。
func(6, 7); // 报错
console.log(result);
var func = function(a, b) {
return a + b;
}
因此,
如果函数经常使用,选择“函数声明”方式定义函数,这种方式无论在哪里定义都能先初始化该函数。
如果函数不经常使用,或函数代码量非常庞大,选择“函数表达式声明”方式定义函数“,这种方式避免了函数初始化都需要在程序开头花费时间。
1.6、匿名函数
没有命名的函数
(1)用在绑定事件的时候
document.onclick = function () {
alert(1);
}
(2)回调函数
setInterval(function () {
console.log(444);
},1000);
(3)立即执行函数
函数定义完,立即被调用,这种函数叫做立即执行函数。立即执行函数往往只会执行一次。
(function(num1, num2){
console.log("num1 = "+ num1);
console.log("num2 = "+ num2);
})(100, 101);
这里引入了闭包的概念
( function(形参) )( 实参 )
1.7、函数是一种数据类型
- 函数是一种引用数据类型,属于Object类型。
- "函数名"是指向对应函数体的指针(地址),"函数名()"是函数返回的结果。
function fn() {
return undefined;
}
console.log(typeof fn); //function
console.log(typeof fn()); //undefined
1.8、回调函数
- 回调函数就是被函数调用的函数。
- 如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。
- "函数名"就是指向对应函数体的指针(地址)
- 多用于递归
function add(num1, num2){return num1 + num2;}
function sub(num1, num2){return num1 - num2;}
function mul(num1, num2){return num1 * num2;}
function divide(num1, num2){return num1 / num2;}
function cal(num1, num2, func) {
return func(num1, num2);
}
var result1 = cal(10, 20, add);
var result2 = cal(10, 20, sub);
var result3 = cal(10, 20, mul);
var result4 = cal(10, 20, divide);
console.log(result1); // 30
console.log(result2); // -10
console.log(result3); // 200
console.log(result4); // 0.5
1.9、变量的作用域
1.9.1、 作用域
变量可以起作用的范围
1.9.2、 全局变量,局部变量
- a是全局变量,从头至尾都能被认出来
- b是局部变量,只有在它所在的函数代码块内,它才能被认出来。
var a = 1;
function fn(){
var b = 2;
console.log("In function, a = " + a); // a = 1
console.log("In function, b = " + b); // b = 2
}
fn();
console.log("Out of function, a = " + a); // a = 1
console.log("Out of function, b = " + b); // 报错
1.9.3、 注意
(1)不使用var声明的变量是全局变量(不推荐使用)
// 这里的b没有用var声明,调用函数之后就创建为全局变量
var a = 1;
function fn(){
b = 2;
}
fn();
console.log("Out of function, a = " + a); // a = 1
console.log("Out of function, b = " + b); // b = 2
(2)变量退出作用域之后才会销毁,全局变量关闭网页或浏览器才会销毁
1.9.4、块级作用域
(1)非函数所属的大括号内并不算一个作用域,只有函数的大括号内才算一个作用域
(2)作用域内用var声明的变量是该作用域的局部变量
// 说明非函数的大括号内并不算一个作用域
{var name = "David";}
console.log(name); // David
// 说明非函数的大括号内并不算一个作用域
var num = 5;
if (num > 3) {
var sum = 7;
}
console.log(sum); // 7
(3)ES6之后,用let声明变量
ES6之后,若要将非函数所属的大括号内视为一个作用域,可以用let声明变量,该变量的作用域为这个大括号内
ES6的块级作用域
用let命令新增了块级作用域,外层作用域无法获取到内层作用域,非常安全明了。即使外层和内层都使用相同变量名,也都互不干扰。
https://www.cnblogs.com/guanqiweb/p/10282574.html
(4)其它语言中变量i只能在for循环内部访问(局部变量),JS比较特殊
for (var i = 0; i < 10; i++) {
}
console.log(i); //10
1.9.5、作用域链
var color = "yellow";
function getColor() {
var anotherColor = "red";
function swapColor() {
var tmpColor = color;
color = anotherColor;
anotherColor = tmpColor;
}
swapColor();
}
getColor();
console.log(color); // "red"
1.9.6、 预解析
(1)概念
- js代码的执行是由浏览器中的js解析器来执行的
- js解析器执行js代码的时候,分为两个过程:预解析过程和代码执行过程。
(2)预解析过程
- 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值。
- 把函数的声明提升到当前作用域的最前面,只会提升声明,不会提升调用。
- 先提升var,再提升function
console.log(a); // undefined
var a = 10;
console.log(a); // 10
相当于
var a;
console.log(a); // undefined
a = 10;
console.log(a); // 10
console.log(fn);
//ƒ fn() {
// console.log('我是函数');
//}
function fn() {
console.log('我是函数');
}
var fn = "我是变量";
console.log(fn); //“我是变量”
相当于
var fn;
function fn() {
console.log('我是函数');
}
fn = "我是变量";
console.log(fn); // function的声明后于var的声明,故funtion的声明把var的声明覆盖了
b、c前面没有var声明,所以是全局变量,a前有var声明,是局部变量,故运行第四行的console.log(a);时会报错
f1();
console.log(c);
console.log(b);
console.log(a);
function f1(){
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
写在最后
如果您觉得文章对您有帮助,不要吝惜您的“点赞”呀!