函数是一段可以反复调用的代码块

函数的声明

JavaScript 有三种声明函数的方法

1、function 命令: function命令声明的代码区块,就是一个函数。function命令后面是函数名,函数名后面是一对圆括号,里面是传入函数的参数。函数体放在大括号里面。

  1. function print(s) {
  2. console.log(s);
  3. }
  4. //调用
  5. print(3)//输出3

2、函数表达式 除了用function命令声明函数,还可以采用变量赋值的写法。

  1. var print = function(s) {
  2. console.log(s);
  3. };
  4. //调用
  5. print(3)//输出3

3、Function 构造函数 第三种声明函数的方式是Function构造函数。
这种声明函数的方式非常不直观,几乎无人使用

  1. var add = new Function(
  2. 'x',
  3. 'y',
  4. 'return x + y'
  5. );
  6. // 等同于
  7. function add(x, y) {
  8. return x + y;
  9. }

实时效果反馈
1. 创建函数的方式一下哪种方式是错误的:
A function print(s) {console.log(s);}
B var print = function(s) {console.log(s);};
C Array print(s) {console.log(s);}
D var add = new Function(‘x’,’y’,’return x + y’);

答案
1=>C

函数的重复声明

如果同一个函数被多次声明,后面的声明就会覆盖前面的声明

  1. function f() {
  2. console.log("sxt");
  3. }
  4. f() // itbaizhan
  5. function f() {
  6. console.log("itbaizhan");
  7. }
  8. f() // itbaizhan

⚠️注意:在日后的工作中
1、命名要规范
2、相同的操作,不需要做多次

实时效果反馈
1. 下列代码的执行结果是:

  1. var fn1 = function(){
  2. console.log("向左走");
  3. }
  4. var fn1 = function(){
  5. console.log("向右走");
  6. }
  7. fn1()

A 报错
B 向左走
C 向右走
D 向左走 向右走

答案
1=>C

函数名的提升

JavaScript 引擎将函数名视同变量名,所以采用function命令声明函数时,整个函数会像变量声明一样,被提升到代码头部。

  1. add();
  2. function add() {}

但是,如果采用赋值语句定义函数,JavaScript 就会报错。

  1. add();
  2. var add = function (){};
  3. // TypeError: undefined is not a function

⚠️注意:不能在条件语句中声明函数
根据 ES5 的规范,不得在非函数的代码块中声明函数,最常见的情况就是if语句

  1. if (true) {
  2. function add() {}
  3. }

实时效果反馈
1. 下列代码执行结果是:

  1. fn();
  2. function fn() {
  3. console.log("欢迎来到前端课堂");
  4. }

A undefined
B 欢迎来到前端课堂
C 报错
D null

答案
1=>B

函数作用域

作用域(scope)指的是变量存在的范围,Javascript 有两种作用域:一种是全局作用域,变量在整个程序中一直存在,所有地方都可以读取;另一种是函数作用域,变量只在函数内部存在
函数外部声明的变量就是全局变量(global variable),它可以在函数内部读取

  1. var num = 1;
  2. function add() {
  3. console.log(num);
  4. }
  5. add()
  6. // num

在函数内部定义的变量,外部无法读取,称为“局部变量”(local variable)

  1. function add(){
  2. var num = 1;
  3. }
  4. num // ReferenceError: num is not defined

函数内部定义的变量,会在该作用域内覆盖同名全局变量

  1. var num = 1;
  2. function add(){
  3. var num = 2;
  4. console.log(num);
  5. }
  6. add() // 2
  7. num // 1

注意,对于var命令来说,局部变量只能在函数内部声明,在其他区块中声明,一律都是全局变量

  1. if (true) {
  2. var num = 5;
  3. }
  4. console.log(num); // 5

函数内部的变量提升

与全局作用域一样,函数作用域内部也会产生“变量提升”现象。var命令声明的变量,不管在什么位置,变量声明都会被提升到函数体的头部

  1. function foo() {
  2. console.log(names);
  3. var names = 'itbaizhan';
  4. }
  5. foo()

实时效果反馈
1. 下列代码执行结果是:

  1. var name = "haha";
  2. function getName(){
  3. var name = "sxt";
  4. console.log(name);
  5. }
  6. console.log(name);
  7. getName();

A haha haha
B sxt sxt
C haha sxt
D sxt haha

答案
1=>C

函数参数

函数运行的时候,有时需要提供外部数据,不同的外部数据会得到不同的结果,这种外部数据就叫参数

  1. function square(x) {
  2. console.log(x * x);
  3. }
  4. square(2) // 4
  5. square(3) // 9

参数的省略

函数参数不是必需的,Javascript 允许省略参数

  1. function add(a, b) {
  2. console.log(a);
  3. }
  4. add(1, 2, 3) // 1
  5. add(1) // 1
  6. add() // undefined
  7. add.length // 2

传递方式

函数参数如果是原始类型的值(数值、字符串、布尔值),传递方式是传值传递(passes by value)。这意味着,在函数体内修改参数值,不会影响到函数外部

  1. var p = 2;
  2. function fn(p) {
  3. p = 3;
  4. }
  5. fn(p);
  6. p // 2

同名参数

如果有同名的参数,则取最后出现的那个值

  1. function add(a, a) {
  2. console.log(a);
  3. }
  4. add(1, 2) // 2

arguments 对象

由于 JavaScript 允许函数有不定数目的参数,所以需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来

  1. var list = function (one) {
  2. console.log(arguments[0]);
  3. console.log(arguments[1]);
  4. console.log(arguments[2]);
  5. }
  6. list(1, 2, 3)

arguments 与数组的关系

需要注意的是,虽然arguments很像数组,但它是一个对象。数组专有的方法(比如slice和forEach),不能在arguments对象上直接使用。
如果要让arguments对象使用数组方法,真正的解决方法是将arguments转为真正的数组

  1. var args = [];
  2. for (var i = 0; i < arguments.length; i++) {
  3. args.push(arguments[i]);
  4. }

实时效果反馈
1. 下列代码执行结果是:

  1. function add(a, a, b) {
  2. console.log(a + b);
  3. }
  4. add(10,20,30)

A 30
B 40
C 50
D 60

答案
1=>C

函数返回值

JavaScript函数提供两个接口实现与外界的交互,其中参数作为入口,接收外界信息;返回值作为出口,把运算结果反馈给外界。
在函数体内,使用 return 语句可以设置函数的返回值。

  1. function getName(name){
  2. return name;
  3. }

可以定义一个变量,来接收该结果

  1. function getName(name){
  2. return name;
  3. }
  4. var myName = getName("itbaizhan")
  5. console.log(myName); // itbaizhan

如果return语句后不跟任何值就相当于返回一个undefined,如果函数中不写return,则也会返回undefined

  1. function getName(name){
  2. return;
  3. }
  4. var myName = getName("itbaizhan")
  5. console.log(myName); // undefined
  6. function getName(name){
  7. }
  8. var myName = getName("itbaizhan")
  9. console.log(myName); // undefined

在函数中return后的语句都不会执行

  1. function getName(name){
  2. return name;
  3. console.log("我不会执行");
  4. }
  5. var myName = getName("itbaizhan")
  6. console.log(myName);

实时效果反馈
1. 下列函数执行输出“haha”,横线处应该填写的代码是:

  1. function getName(name) {
  2. ___;
  3. }
  4. var myName = getName("haha")
  5. console.log(myName); // haha

A return name
B return
C name
D return “haha”

答案
1=>A

立即调用的函数表达式(IIFE)

在 Javascript 中,圆括号()是一种运算符,跟在函数名之后,表示调用该函数。比如,print()就表示调用print函数。那如何让函数自己执行呢?

  1. (function(){ /* code */ }());
  2. // 或者
  3. (function(){ /* code */ })();

eval 命令

eval命令的作用是,将字符串当作语句执行

  1. eval('var a = 1;');
  2. a // 1

实时效果反馈
1. 下列代码,横线处应该填写的代码是:

  1. var str = "hello";
  2. (function(str) {
  3. console.log(str.split("").reverse().join(""));
  4. })___;

A ()
B str
C [str]
D (str)

答案
1=>D

函数的应用

实现一个函数,要求传入数组,返回排序之后的数组

  1. function mySort(arr) {
  2. for (var i = 0; i < arr.length - 1; i++) {
  3. for (var j = 0; j < arr.length - 1 - i; j++) {
  4. if (arr[j] > arr[j + 1]) {
  5. var temp = arr[j];
  6. arr[j] = arr[j + 1];
  7. arr[j + 1] = temp;
  8. }
  9. }
  10. }
  11. return arr
  12. }

实现阶乘:5!的结果

  1. function fact(num){
  2. if(num<=1){
  3. return 1
  4. }else{
  5. return num*fact(num-1)
  6. }
  7. }

实时效果反馈
1. 下列代码,横线处应该填写的代码是:

  1. function fact(num){
  2. if(num<=1){
  3. return 1
  4. }else{
  5. return ___
  6. }
  7. }

A fact(num-1)
B numfact(num-1)
C num
(num-1)
D fact*(num-1)

答案
1=>B

对象概述

什么是对象?对象(object)是 JavaScript 语言的核心概念,也是最重要的数据类型
简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合
image.png

  1. var user = {
  2. name: 'itbaizhan',
  3. age: '13'
  4. };

如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),则必须加上引号,否则会报错

  1. // 报错
  2. var obj = {
  3. 1p: 'Hello World'
  4. };
  5. // 不报错
  6. var obj = {
  7. '1p': 'Hello World',
  8. 'h w': 'Hello World',
  9. 'p+q': 'Hello World'
  10. };

对象的每一个键名又称为“属性”(property),它的“键值”可以是任何数据类型。如果一个属性的值为函数,通常把这个属性称为“方法”,它可以像函数那样调用

  1. var user = {
  2. getName: function (name) {
  3. return name;
  4. }
  5. };
  6. user.getName("itbaizhan") // itbaizhan

如果属性的值还是一个对象,就形成了链式引用

  1. var user = {
  2. name:"itbaizhan",
  3. age:13,
  4. container:{
  5. frontEnd:["Web前端","Android","iOS"],
  6. backEnd:["Java","Python"]
  7. }
  8. }
  9. user.container.frontEnd // ["Web前端","Android","iOS"]

实时效果反馈
1. 下列关于对象描述正确的是:
A 对象是条件语句,负责进行判断
B 对象是一段反复调用的代码块
C 对象就是一组“键值对”(key-value)的集合
D 对象是按次序排列的一组值。每个值的位置都有编号(从0开始)
2. 下列关于对象的代码,画横线处应该填写的代码是:

  1. var obj = {
  2. ___: '积累与沉淀,提供最好的服务'
  3. };
  4. obj['13sxt']; // 积累与沉淀,提供最好的服务

A [13sxt]
B {13sxt}
C 13sxt
D ‘13sxt’

答案
1=>C 2=>D

对象属性

读取属性

读取对象的属性,有两种方法,一种是使用点运算符,还有一种是使用方括号运算符

  1. var user = {
  2. hello: 'Hello World'
  3. };
  4. user.hello // "Hello World"
  5. user['hello'] // "Hello World"

⚠️注意:如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理

属性的赋值

点运算符和方括号运算符,不仅可以用来读取值,还可以用来赋值

  1. var obj = {};
  2. obj.name = 'itbaizhan';
  3. obj['age'] = 13;

JavaScript 允许属性的“后绑定”,也就是说,你可以在任意时刻新增属性,没必要在定义对象的时候,就定义好属性

  1. var user = { name: "itbaizhan" };
  2. // 等价于
  3. var user = {};
  4. user.name = "itbaizhan";

查看所有属性

查看一个对象本身的所有属性,可以使用Object.keys方法

  1. var user = {
  2. key1: 1,
  3. key2: 2
  4. };
  5. Object.keys(user); // ['key1', 'key2']

delete 命令

delete命令用于删除对象的属性,删除成功后返回true

  1. var user = { name: "itbaizhan" };
  2. Object.keys(user) // ["name"]
  3. delete user.name // true
  4. user.name // undefined
  5. Object.keys(user) // []

⚠️注意:删除一个不存在的属性,delete不报错,而且返回true

  1. var user = {};
  2. delete user.name // true

只有一种情况,delete命令会返回false,那就是该属性存在,且不得删除(使用率极低)

for…in 循环

for…in循环用来遍历一个对象的全部属性

  1. var user = {
  2. name:"itbaizhan",
  3. age:13
  4. };
  5. for (var i in user) {
  6. console.log(user[i]); // itbaizhan 13
  7. }

实时效果反馈
1. 下列关于对象代码运行结果,正确的是:

  1. var user = {
  2. name: "itbaizhan",
  3. age: 13
  4. };
  5. user.job = "it";
  6. user['location'] = "beijing";
  7. for (var i in user) {
  8. console.log(user[i]);
  9. }

A itbaizhan 13
B itbaizhan 13 it
C itbaizhan 13 it beijing
D name age job location

答案
1=>C

对象方法

image.png
Object对象的方法分成两类:Object本身的方法与Object的实例方法

Object对象本身的方法

所谓”本身的方法“就是直接定义在Object对象的方法

  1. Object.print = function (info) {
  2. console.log(info)
  3. };
  4. Object.print("hello");

Object的实例方法

所谓实例方法就是定义在Object原型对象Object.prototype上的方法。它可以被Object实例直接使用

  1. Object.prototype.print = function (name) {
  2. console.log(name);
  3. };
  4. var user = {
  5. name:'itbaizhan'
  6. }
  7. user.print(user.name);

实时效果反馈
1. 下列关于对象代码运行结果,正确的是:

  1. Object.___.print = function (name) {
  2. console.log(name);
  3. };
  4. var user = {
  5. name: 'itbaizhan'
  6. }
  7. user.print(user.name);

A user.print
B prototype
C user
D user.name

答案
1=>B

函数应用注意事项

函数中调用函数

现有两个函数hello()和world(),那么是可以通过一个函数调用另一个函数运行的

函数体使用规范

  1. 总行数不要超过50行
  2. 不同的业务分割成不同的函数处理

需求:创建一个函数,传递两个参数,返回两个参数的相乘和相加的和

  1. function result(x,y){
  2. var sum = mult(x,y) + add(x,y);
  3. console.log(sum)
  4. }
  5. function mult(x,y){
  6. return x * y;
  7. }
  8. function add(x,y){
  9. return x + y;
  10. }