Blogger Information
Blog 17
fans 0
comment 0
visits 14806
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
js基础知识:变量作用域与闭包,以及类与类的继承
未来星
Original
701 people have browsed it

一、作用域

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());
Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:很多概念其实很好理解 , 觉得难很有可能是想多了,设计者可能都没学习者考虑的多
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post