Javascript函数&变量的作用域&&方法(三)

以下是对JavaScript函数的学习


函数

定义函数

  1. 定义方式一

绝对值函数

1
2
3
4
5
6
7
function abs(x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}

一旦执行到return代表函数结束,返回结果!
如果没有执行return,函数执行完也会返回结果,结果就是undefined

  1. 定义方式二

    1
    2
    3
    4
    5
    6
    7
    var abs = function (x) {
    if (x >= 0) {
    return x;
    } else {
    return -x;
    }
    }

    function(x){….}这是一个匿名函数,但是可以把结果赋值给abs,通过abs就可以调用函数!
    方式一和方式二等价!

  2. 调用函数

    1
    2
    abs(10)  //10
    abs(-10) //10

    参数问题: JavaScript可以传任意个参数,也可以不传递参数~
    参数尽量是否存在的问题?
    假设不存在参数,如何规避?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var abs = function (x) {
    // 手动抛出异常来判断
    if (typeof x !== 'number') {
    throw 'Not a Number';
    }
    if (x >= 0) {
    return x;
    } else {
    return -x;
    }
    };
  3. arguments
    arguments是一个JS免费赠送的关键字:
    代表,传递进来的所有的参数,是一个数组!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var abs = function (x) {
    console.log('x=>' + x);
    for (var i = 0; i < arguments.length; i++) {
    console.log(arguments[i]);
    }
    if (x >= 0) {
    return x;
    } else {
    return -x;
    }
    };

    问题: arguments包含所有的参数,我们有时候使用多余的参数来进行附加操作。需要排除已有参数~

  4. rest
    ES6引入的新特性,获取除了已经定义的参数之外的所有参数~
    以前

    1
    2
    3
    4
    5
    if(arguments.length>2){
    for(var i=2;i<arguments.length;i++){

    }
    }

    ES6引入的新特性,获取除了已经定义的参数之外的所有参数~

    1
    2
    3
    4
    5
    function aaa(a, b, ...rest) {
    console.log('a=>' + a);
    console.log('b=>' + b);
    console.log(rest);
    }

    rest 参数只能写在最后面,必须用…标识。

变量的作用域

  1. 在JavaScript中,var定义的变量实际是有作用域的。
    假设在函数体中声明,则在函数体外不可以使用~(非要想实现的话后面可以研究以下闭包)

    1
    2
    3
    4
    5
    6
    'use strict';
    function qj() {
    var i = 1;
    x = x + 1;
    }
    x = x + 2; //Uncaught ReferenceError: x is not defined
  2. 如果两个函数使用了相同的变量名,只要在函数内部,就不冲突

    1
    2
    3
    4
    5
    6
    7
    8
    9
    'use strict';
    function qj() {
    var i = 1;
    x = x + 1;
    }
    function qj2() {
    var x = 'a';
    X = X + 1;
    }
  3. 假设,内部函数变量和外部函数的变量,重名!

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    function qj() {
    var x = 1;
    function qj2() {
    var x = 'A';
    console.log('inner' + x); //innerA
    }
    console.log('outer' + x); //outer1
    qj2();
    }
    qj();

    假设在JavaScript中函数查找变量从自身函数开始~,由“内”向“外”查找,假设外部存在这个同名的函数变量,则内部函数会屏蔽外部函数的变量。

  4. 提升变量的作用域

    1
    2
    3
    4
    5
    function qj() {
    var x = 'x' + y;
    console.log(x);
    var y = 'y';
    }

    结果: xundefined
    说明:js执行引擎,自动提升了y的声明,但是不会提升变量y的赋值;

    1
    2
    3
    4
    5
    6
    function qj2() {
    var y;
    var x = 'x' + y;
    console.log(x);
    y = 'y';
    }

    这个是在JavaScript建立之初就存在的特性。养成规范:所有的变量定义都放在函数的头部,不要乱放,便于代码维护。

    1
    2
    3
    4
    5
    6
    7
    function qj2() {
    var x = 1;
    y = x + 1;
    z, i, a; //undefined

    //之后随意用
    }
  5. 全局函数

    1
    2
    3
    4
    5
    6
    7
    //全局变量
    var x=1;
    function f(){
    console.log(x);
    }
    f();
    console.log(x);
  6. 全局对象window

    1
    2
    3
    var x = 'xxx';
    window.alert(x);
    window.alert(window.x); //默认所有的全局变量,都会自动绑定在window对象下

alter()这个函数本身也是一个window变量

1
2
3
4
5
6
7
8
9
10
11
var x = 'xxx';
window.alert(x);
// window.alert(window.x); //默认所有的全局变量,都会自动绑定在window对象下
var old_alter = window.alert;
// old_alter(x);
window.alert = function () {};
//发现alter()失效了
window.alert(123);
//恢复
window.alert = old_alter;
window.alert(456);

JavaScript实际上只有一个全局作用域,任何变量(函数也可以视为变量),假如没有在函数作用范围内找到,就会向外查找。如果在全局作用域都没有找到,报错ReferenceError.
7. 规范
由于我们所有的全局变量都会绑定在我们的window上,如果不同的js文件,使用了相同的全局变量,冲突->如何能够减少冲突?

1
2
3
4
5
6
7
//唯一全局变量
var all = {};
//定义全局变量
all.name = 'DragonPeng';
all.add = function (a, b) {
return a + b;
};

把自己的代码全部放入自己定义的唯一空间命名中,降低全局命名冲突的问题~

  1. 局部作用域let

    1
    2
    3
    4
    5
    6
    function aaa() {
    for (var i = 0; i < 100; i++) {
    console.log(i);
    }
    console.log(i + 1); //问题?i出了这个作用域还可以使用
    }

    ES6 let关键字,解决局部作用域冲突问题!

    1
    2
    3
    4
    5
    6
    function aaa() {
    for (let i = 0; i < 100; i++) {
    console.log(i);
    }
    console.log(i + 1); //Uncaught ReferenceError: i is not defined
    }

    建议大家都用let去定义局部作用域的变量

  2. 常量const
    在ES6之前,怎么定义常量,只有用全部大写字母命名的变量就是常量;建议不要修改这样的值

    1
    2
    3
    4
    var PI = '3.14';
    console.log(PI);
    PI = '214';//可以改变这个值
    console.log(PI);

    在ES6引入了常量关键字 const

    1
    2
    3
    4
    const PI = '3.14';
    console.log(PI);
    PI = '123';//Uncaught TypeError: Assignment to constant variable.
    console.log(PI);

    方法

    定义方法:
    方法就是把函数放在对象的里面,对象只有两个东西:属性和方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
          var student = {
    name: 'haha',
    birth: 2000,
    //方法
    age: function () {
    //今年-出生的年
    var now = new Date().getFullYear();
    return now - this.birth;
    },
    };
    //属性
    student.name
    //方法,一定要带()
    student.age()

    this代表什么?拆开上面的代码看看~

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    function getAge() {
    //今年-出生的年
    var now = new Date().getFullYear();
    return now - this.birth;
    }
    var student = {
    name: 'haha',
    birth: 2000,
    age: getAge,
    };
    //student.age() //ok
    // getAge() NaN window

    this是无法指向的,是默认指向调用它的那个对象;

applay

1
2
3
4
5
6
7
8
9
10
11
12
13
function getAge() {
//今年-出生的年
var now = new Date().getFullYear();
return now - this.birth;
}
var student = {
name: 'haha',
birth: 2000,
age: getAge,
};
//student.age() //ok
// getAge() NaN
getAge.apply(student, []); //this,指向了student,参数为空

基于B站视频学习 特别感谢up主 遇见狂神说