博客列表 >js基础知识:变量作用域与闭包,以及类与类的继承

js基础知识:变量作用域与闭包,以及类与类的继承

未来星
未来星原创
2021年04月12日 17:55:14702浏览

一、作用域

js中变量的作用域是指一个变量的作用范围。包括:全局作用域函数作用域块作用域(ES6后新增)。

1、全局作用域:

(1) 全局作用域在页面打开时被创建,页面关闭时被销毁;
(2) 编写在script标签中的变量和函数,作用域为全局,在页面的任意位置都可以访问到;
(3) 在全局作用域中有全局对象window,代表一个浏览器窗口,由浏览器创建,可以直接调用;
(4) 全局作用域中声明的变量和函数会作为window对象的属性和方法保存;

  1. // 作用域: 全局, 函数, 块
  2. // 1. 全局作用域,默认的,不可删除
  3. let site = "京东商城";
  4. console.log(site);
  5. // 由全局对象调用的
  6. // 全局对象: 如果在是浏览器中运行js,那么全局对象就是window
  7. console.log(window.site);

2、函数作用域:

(1) 调用函数时,函数作用域被创建,函数执行完毕,函数作用域被销毁;
(2) 每调用一次函数就会创建一个新的函数作用域,他们之间是相互独立的;
(3) 在函数作用域中可以访问到全局作用域的变量,在函数外无法访问到函数作用域内的变量;
(4) 在函数作用域中访问变量、函数时,会先在自身作用域中寻找,若没有找到,则会到函数的上一级作用域中寻找,一直到全局作用域;

  1. // 2. 函数作用域
  2. function getSite() {
  3. // site是声明在函数外部的全局变量
  4. // 在函数内部可以访问到外部的全局变量
  5. // 私有成员,仅限在当前作用内访问, 外部不可见
  6. let domain = "jd.com";
  7. return `${site} [ ${domain} ]`;
  8. // 这里要返回一个叫site的变量
  9. // 有一个查询的过程, 先在自身的作用域找一个有没有一个叫site
  10. // 如果有则直接返回它
  11. // 如果函数中没有这个site,则自动函数的上一级作用域中去查看site
  12. // 全局正好有一个site,于是就返回了全局的site
  13. // 内部的site ---> 到它的上一级作用域中去查找
  14. // 上面的查询变量的过程,就是是一个链式查询的一个过程,称为:作用域链
  15. }
  16. console.log(getSite());
  17. // console.log(domain);

3、块作用域:

ES6中新增了块级作用域,块作用域由 { }包括,if语句和for、while语句里面的{ }也属于块作用域。

  1. // 3. 块作用域
  2. // if (), while()
  3. {
  4. // let a = 1;
  5. // const B = "hello";
  6. // var:不支持块作用域
  7. var a = 1;
  8. var B = "hello";
  9. }
  10. console.log(a, B);

二、闭包

如果在一个内部函数里,对在外部作用域(但不是全局作用域)的变量进行引用,那么内部函数就被认为是闭包(closure)。闭包的本质就是在一个函数内部创建另一个函数

  1. // 4. 闭包
  2. let c = 100;
  3. function sum(a, b) {
  4. // return a + b;
  5. // 现在已经产生了闭包了
  6. // 函数中的变量按来源有二种类型
  7. // 1. 形参: a, b , 这是函数自有的
  8. // 2. 自由变量: c, c并不是函数自有的
  9. // 当前的函数可以访问到上一级/外部的自由变量
  10. // 闭包: 能够访问自由变量的函数
  11. // 自由变量,函数参数以外的变量
  12. // 理论上讲,所有函数都是闭包
  13. return a + b + c;
  14. }
  15. console.log(sum(4, 5));
  16. // 通过闭包来访问内部的私有变量;
  17. function demo1() {
  18. // 私有变量
  19. let email = "abc@qq.com";
  20. // return email;
  21. return function d() {
  22. // 对于这个子函数来说,email就是它的自由变量
  23. return email;
  24. };
  25. }
  26. // console.log(email);
  27. // let f = demo1();
  28. // console.log(f());
  29. console.log(demo1());

三、类与继承

JS并没有类(class)的概念,通常都是通过构造函数来实现对象(class)属性的定义,然后通过new这个关键字来实例化。
构造函数的三大特点:
(1) 构造函数的函数名的第一个字母通常大写;
(2) 函数体内使用this关键字,代表所要生成的对象实例;
(3) 生成对象的时候,必须使用new命令来调用构造函数;

  1. // 构造函数来模拟类(对象的模板)
  2. function User(name, email) {
  3. this.name = name;
  4. this.email = email;
  5. // show()输出属性
  6. // this.show = function () {
  7. // return { name: this.name, email: this.email };
  8. // };
  9. }
  10. // 构造函数对象的原型对象上的成员,可以被所有实例所共享
  11. // es6
  12. class User1 {
  13. // 构造方法:初始化对象的
  14. constructor(name, email) {
  15. this.name = name;
  16. this.email = email;
  17. }
  18. // 原型方法(共享方法),通过对象来调用的
  19. show() {
  20. return { name: this.name, email: this.email, age: this.#age };
  21. }
  22. // 静态方法: 不需要实例化(new class),直接用类来调用
  23. static fetch() {
  24. // return "static function";
  25. // 静态成员中的this表示的就是当前的类
  26. return this.userName;
  27. }
  28. // 静态属性/变量
  29. static userName = "小马哥";
  30. // 私有成员
  31. #age = 50;
  32. // 还可以声明访问器属性: 伪装成属性的方法,有get,set
  33. // 使用访问器属性来访问私有成员
  34. get age() {
  35. return this.#age;
  36. }
  37. set age(value) {
  38. if (value >= 18 && value < 60) this.#age = value;
  39. else console.log("年龄非法");
  40. }
  41. }
  42. const user1 = new User1("大牛", "tp@qq.com");
  43. // console.log(user1);
  44. console.log(user1.show());
  45. // 静态方法直接用类调用
  46. console.log(User1.fetch());
  47. // console.log(user1.#age);
  48. console.log("my age = ", user1.age);
  49. user1.age = 160;
  50. console.log("my age = ", user1.age);
  51. user1.age = 32;
  52. console.log("my age = ", user1.age);

继承,首先需要一个父类(Father),将父类的实例作为子类的原型,并对父类进行一些扩展。

  1. // 继承,通常是对父类进行一些扩展(添加一些新的属性或方法)
  2. class Child extends User1 {
  3. constructor(name, email, gender) {
  4. // 第一步必须将父类的构造方法来执行一下,否则this用不了
  5. super(name, email);
  6. // 第二步给子类的新成中去初始化
  7. this.gender = gender;
  8. }
  9. // 父类的原型方法
  10. show() {
  11. return { name: this.name, email: this.email, gender: this.gender };
  12. }
  13. }
  14. const child = new Child("大牛", "niu@qq.com", "男");
  15. console.log(child.show());
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议