笔记来源 尚硅谷最新版JavaScript基础全套教程完整版(140集实战教学,JS从入门到精通)_哔哩哔哩_bilibili

作用域

作用域指一个变量的作用的范围

在JS中一共有两种作用域:

  • 全局作用域
  • 函数作用域

1、全局作用域

直接编写在script标签中的JS代码,都在全局作用域

全局作用域在页面打开时创建,在页面关闭时销毁

在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,由浏览器创建,可以直接使用

在全局作用域中:

  • 创建的变量都会作为window对象的属性保存
  • 创建的函数都会作为window对象的方法保存

全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到

  1. var a = 3;
  2. console.log(window.a); //3
  3. console.log(a); //3
  4. b = 3;
  5. console.log(b); //3

1.1、变量的声明提前

使用var关键字声明的变量,会在所有的代码执行之前被声明

但是如果声明变量时不适用var关键字,则变量不会被声明提前

  1. // 1、变量的声明提前
  2. console.log("a = " + a); // a = undefined
  3. var a = "abc";
  4. // ======相当于======
  5. var a;
  6. console.log("a = " + a); // a = undefined
  7. a = "abc";
  8. // 2、没有变量的声明提前,报错
  9. console.log("b = " + b); // UncaughtReferenceError: b is not defined
  10. b = "abc";
  11. // ======相当于======
  12. console.log("b = " + b); // UncaughtReferenceError: b is not defined
  13. window.b = "abc";

1.2、函数的声明提前

使用函数声明形式创建的函数function

  1. 函数(){
  2. 语句...
  3. }

它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数

  1. fun1(); // fun1...
  2. fun2(); // UncaughtTypeError: fun2 is not a function
  3. // 函数声明,会被提前创建
  4. function fun1(){
  5. console.log("fun1...");
  6. }
  7. // 函数表达式,不会被提前创建(变量会被提前声明,但函数不会被提前创建)
  8. var fun2 = function(){
  9. console.log("fun2...");
  10. }

2、函数作用域

调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁

每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的

  • 在函数作用域中可以访问到全局作用域的变量
  • 在全局作用域中无法访问到函数作用域的变量

当在函数作用域操作一个变量时,它会先在自身作用域中寻找,

  • 如果有就直接使用
  • 如果没有则向上一级作用域中寻找,直到找到全局作用域
  • 如果全局作用域中依然没有找到,则会报错

在函数中要访问全局变量可以使用window对象

  1. var a = 10;
  2. function fun2(){
  3. var a = 20;
  4. function fun3(){
  5. var a = 30;
  6. console.log("fun3 ==> a = " + a); // fun3 ==> a = 30
  7. }
  8. fun3();
  9. console.log("fun2 ==>a = " + a); // fun2 ==>a = 20
  10. console.log("a = " + window.a); // a = 10
  11. }
  12. fun2();
  13. console.log("a = " + a); // a = 10

在函数作用域也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明

函数声明也会在函数中所有的代码执行之前执行

  1. // 在函数作用域也有声明提前的特性,使用`var`关键字声明的变量,会在函数中所有的代码执行之前被声明
  2. function func1(){
  3. console.log(a);
  4. var a = "func1";
  5. // 函数声明也会在函数中所有的代码执行之前执行
  6. func2(); // fun2...
  7. function func2(){
  8. console.log("fun2...");
  9. }
  10. }
  11. func1(); // undefined

在函数中,不适用var声明的变量都会成为全局变量

  1. // 函数声明且调用
  2. func3();
  3. function func3() {
  4. a = 4;
  5. }
  6. console.log("a = " + window.a); // a = 4
  7. console.log("a = " + window["a"]); // a = 4
  8. console.log("a = " + a); // a = 4
  9. // 函数声明不调用
  10. function func4() {
  11. b = 4;
  12. }
  13. console.log("b = " + window.b); // b = 4
  14. console.log("b = " + window["b"]); // b = 4
  15. console.log("b = " + b); // UncaughtReferenceError: b is not defined

定义形参就相当于在函数作用域中声明了变量

  1. var e = 10;
  2. function fun5(e){
  3. console.log(e);
  4. }
  5. fun5(); // undefined
  6. fun5(55); // 55

练习

  1. // 说出以下代码的执行结果
  2. var a = 123;
  3. function fun(){
  4. console.log(a);
  5. }
  6. fun(); // 123
  7. // =====================
  8. var a = 123;
  9. function fun(){
  10. console.log(a);
  11. var a = 456;
  12. }
  13. fun(); // undefined
  14. console.log(a); // 123
  15. // =====================
  16. var a = 123;
  17. function fun(){
  18. console.log(a);
  19. a = 456;
  20. }
  21. fun(); // 123
  22. console.log(a); // 456
  23. // =====================
  24. var a = 123;
  25. function fun(a){
  26. console.log(a);
  27. a = 456;
  28. }
  29. fun(); // undefined
  30. console.log(a); // 123
  31. // =====================
  32. var a = 123;
  33. function fun(a){
  34. console.log(a);
  35. a = 456;
  36. }
  37. fun(789); // 789
  38. console.log(a); // 123

3、this

解析器在调用函数每次都会向函数内部传递进一个隐含的参数,这个隐含的参数就是this

this指向的是一个对象,这个对象我们称为函数执行的上下文对象

根据函数的调用方式的不同,this会指向不同的对象

  • 以函数的形式调用时,this永远都是window
  • 以方法的形式调用时,this就是调用方法的那个对象
  1. // - 以函数的形式调用时,`this`永远都是`window`
  2. function fun(){
  3. console.log(this.name);
  4. }
  5. var name = "ddd"; // ddd
  6. fun();
  7. // - 以方法的形式调用时,`this`就是调用方法的那个对象
  8. var obj = {
  9. name: "孙悟空",
  10. sayName: fun
  11. }
  12. obj.sayName(); // 孙悟空