JS学习快速笔记(二)

111 阅读5分钟

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

函数的意义

在数学中,函数被定义为f(x) = x + 2 类似这样的形式,在后续引用到f(x)我们就知道他指的是x + 2这样的过程。在编程语言中同样也是如此。

当我们重复使用某种过程时,我们就可以把它抽象为一个方法。

function addTow(x){
    return x + 2;
}

当我们再一次需要使用这样的过程时,我们就可以调用方法来代替重复书写过程。

当这样子的过程变得复杂,比如面积公式,他带来的方便程序,相信可以很容易感受到。

定义函数

第一种直接定义

function abs(x) {  // function 为函数声明  abs为函数名称  (x)为函数参数,可以为多个,用逗号隔开 不同于Java不需要定义类型 {}括号为函数体
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}

函数体内部的语句在执行时,一旦执行到return时,函数就执行完毕,并将结果返回

如果没有return语句,函数执行完毕后也会返回结果,只是结果为undefined

第二种 匿名函数

var abs = function (x) {
    if (x >= 0) {
        return x;
    } else {
        return -x;
    }
}; //此处的分号 代表赋值语句 = 的结束。

像这种没有给函数名称命名的函数,为匿名函数。虽然他没有取名,但是他赋值给了变量abs,所以通过变量abs也可以调用该函数。

以上两张方式完全等价。

调用函数

调用函数时,我们只需要写入函数名,并且按照顺序传入参数即可。

abs(1);
//允许传入任意个参数不影响试用,函数会直接抛弃这些多余参数
abs(1,"a");
abs();//返回 NaN 没有传入数据,函数体内x为undefined,计算结果为NaN(Not a Number)

函数内部还会自动有一个arguments关键字,它指向当前函数被传入的所有参数。

function foo(x) {
    console.log('x = ' + x); // 10
    for (var i=0; i<arguments.length; i++) {
        console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
    }
}
foo(10, 20, 30);

arguments最常用的方式,是判断传入参数的个数,要把某个参数变为“可选”参数,就只能通过arguments判断,然后重新调整参数并赋值。

ES6引入了rest参数,可以帮助我们获取多余的参数。

function foo(a, b, ...rest) { //rest参数只能写在最后,前面用...标识
    console.log('a = ' + a);
    console.log('b = ' + b);
    console.log(rest);
}

foo(1, 2, 3, 4, 5);
// 结果:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]

foo(1); //参数没填满 为空数组 不是undefined
// 结果:
// a = 1
// b = undefined
// Array []

注意return

JavaScript引擎有一个在行末自动添加分号的机制。

function foo() {
    return               
        { name: 'foo' };
}

foo(); // undefined

//当你这样写return,自动添加分号的机制该方法会变成

function foo() {
    return; // 自动添加了分号,相当于return undefined;
        { name: 'foo' }; // 这行语句已经没法执行到了
}

作用域

  • 变量只在作用域内可以被引用,函数体内部声明变量,变量的作用于为这个函数的函数体

  • 不同函数体内的同名变量各自独立,互不影响

  • 一个函数的内部函数可以访问外部函数的变量,反之不行。像是流水,从高往低,反过来不行。

  • 内部函数与外部函数的变量重名,内部变量将“屏蔽”外部变量

    JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。

全局作用域

不在任何函数内定义的变量就具有全局作用域,JavaScript默认有一个全局对象window,全局作用域的变量实际上被绑定到window的一个属性

var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // 'Learn JavaScript'

局部作用域

不同于Java,for循环等语句块中是无法定义局部作用域的变量的。ES6引入了新的关键字let,用let代替var可以申明一个局部作用域。

变量提升

JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部。

function foo() {
    var x = 'Hello, ' + y;
    console.log(x);
    var y = 'Bob';
}
//相当于
function foo() {
    var y; // 提升变量y的申明,此时y为undefined
    var x = 'Hello, ' + y;
    console.log(x);
    y = 'Bob';
}

JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。

请严格遵守“在函数内部首先申明所有变量”这一规则

常量

ES6引入了const关键字来定义常量,它具有块级作用域和let类似,和Java中的final关键字类似。

const PI = 3.14; //无法被修改

解构赋值

在ES6中,我们使用解构赋值可以使用这样的方式。

var [x, y, z] = ['hello', 'JavaScript', 'ES6']; // 把数组的各个值赋给各个变量。
let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']]; //注意嵌套层次和位置要保持一致
let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素

我们也可以对对象进行解构赋值

var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school',
    address: {
        city: 'Beijing',
        street: 'No.1 Road',
        zipcode: '100001'
    }
};
var {name, age, passport} = person;
var {name, address: {city, zip}} = person; //注意嵌套层次和位置要保持一致

如果对应的属性不存在,变量将被赋值为undefined

当变量名和属性名不一致

// 把passport属性赋值给变量id:
let {name, passport:id} = person; // 注意: passport不是变量,而是为了让变量id获得passport属性:

解构赋值可以使用默认值

// 如果person对象没有single属性,默认赋值为true:
var {name, single=true} = person;

函数接受一个对象作为参数,使用解构赋值

function buildDate({year, month, day, hour=0, minute=0, second=0}) {
    return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);
}

声明

文章为本人学习JS笔记,用于快速查找知识点以及总结

文章引用:www.liaoxuefeng.com/wiki/102291…