Blogger Information
Blog 18
fans 0
comment 0
visits 10995
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
210402 JavaScript 作用域 闭包 原型 构造函数
xyphpblog
Original
497 people have browsed it

1. 作用域

  • 全局
  • 函数

1.1 全局作用域

  1. <script>
  2. let a = 1;
  3. console.log(a);
  4. //1
  5. </script>

1.2 函数作用域

  1. let a = 1;
  2. //console.log(a);
  3. function foo() {
  4. let a = 5;
  5. return a;
  6. }
  7. console.log(foo());
  8. //5

1.3 块作用域

  • 只有在块作用域中使用let或const声明才有效,使用var无效(作用域会提升)
  1. {
  2. let m = 8;
  3. const M = 9;
  4. }
  5. console.log(M);
  6. console.log(m);
  7. //均会报错

2. 闭包

  • 用来访问函数内部的局部变量
  1. function foo() {
  2. let a = 0;
  3. return function f(params) {
  4. return a;
  5. }
  6. }
  7. let f = foo();
  8. console.log(f());

3. 循环

  • 用于遍历数组,对象

3.1 while loop

  • 数组
  1. const arr = ["cat", "dog", "pig"];
  2. let i = 0;
  3. while (i < arr.length) {
  4. console.log(`animal: ${arr[i]}`);
  5. i += 1;
  6. }
  7. //animal: cat
  8. //animal: dog
  9. //animal: pig

3.2 do…while loop

  • 数组
  1. let i = 1;
  2. do {
  3. i += 1;
  4. console.log(`animal: ${arr[i]}`);
  5. } while (i < arr.length - 1);
  6. //animal: pig

3.3 for…in

  • 对象
  1. const stu = {
  2. id: 1,
  3. name: "Jack",
  4. gender: "male",
  5. graduate: false
  6. }
  7. for (const key in stu) {
  8. console.log("%c%s", "color:green", stu[key]);
  9. }
  10. //1
  11. //Jack
  12. //male
  13. //false

3.3 迭代器

  1. for (const item of arr) {
  2. console.log(item);
  3. }
  4. //animal: cat
  5. //animal: dog
  6. //animal: pig

4. 构造函数和原型

JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。

准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的prototype属性上,而非对象实例本身。

  • 函数本身是对象,其中一个属性为prototype
  • 可作为对象的构造器,构造函数
  • javascript没有“类”的概念,都是通过原型来实现继承

4.1 构造函数

  • 在函数中不再创建对象并返回
  • 命名一般以大写字母开头,以区分构建函数和普通函数
  • 函数作为构造函数使用时,必须使用new关键字
  • 类的实例化:通过构造函数创建对象的过程(此时构造函数可看成类)
  1. function User(name, age) {
  2. this.name = name;
  3. this.age = age;
  4. this.info = function () {
  5. return { name: this.name, age: this.age };
  6. }
  7. }

4.2 原型

  • 每一个函数的特殊属性:prototype
  • 原型函数的实例的proto属性,相当于原型函数的prototype属性
  • 每个实例对象都从原型中继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。
  1. function User(params) {
  2. this.p = params;
  3. }
  4. const user = new User("hehe");
  5. console.log(user);
  6. //user对象的原型
  7. console.log(user.__proto__);
  8. //user构造函数的原型
  9. console.log(User.prototype);
  10. console.log(user.__proto__ === User.prototype);

原型链

  1. 当访问原型函数实例的属性时,会先检查该实例是否具有要访问的属性。
  2. 如果 实例 没有这个属性, 然后浏览器就会在 实例 的 proto 中查找这个属性(也就是 原型函数的.prototype)
  3. 如果 实例 的 proto 有这个属性, 那么它的 proto 上的这个属性就会被使用.
  4. 否则, 如果 实例 的 __proto 没有这个属性, 浏览器就会去查找它的 protoproto ,看它是否有这个属性.
  5. 默认情况下, 所有函数的原型属性的 proto 就是 window.Object.prototype.
  6. 所以 实例 的 protoproto (也就是 原型函数的.prototype 的 proto (也就是 Object.prototype)) 会被查找是否有这个属性.
  7. 如果没有在它里面找到这个属性, 然后就会在 实例 的 protoprotoproto 里面查找.
  8. 然而这有一个问题: 实例 的 protoprotoproto 不存在.
  9. 最后, 原型链上面的所有的 proto 都被找完了, 浏览器所有已经声明了的 proto 上都不存在这个属性
  10. 然后就得出结论,这个属性是 undefined.

常见定义做法:

  • 在构造函数内定义属性
  • 在其prototype属性上定义方法
  1. function User(name, age) {
  2. this.name = name;
  3. this.age = age;
  4. // this.info = function () {
  5. // return { name: this.name, age: this.age };
  6. // }
  7. }
  8. //将info()放到原型prototype属性中
  9. User.prototype.info = function () {
  10. return { name: this.name, age: this.age };
  11. };
  12. //生成对象
  13. const user = new User("Tom", 23);
  14. console.log(user);
  15. //User {name: "Tom", age: 23}
  16. console.log(user.info());
  17. //{name: "Tom", age: 23}

5. 类与继承

  • 子类继承父类的属性
  • 可以重写父类方法
  • 可以有新的属性
  • 不能继承父类的私有属性
  1. class Animal {
  2. //构造方法
  3. constructor(name, leg) {
  4. this.name = name;
  5. this.leg = leg;
  6. }
  7. //原型方法
  8. info() {
  9. return { name: this.name, leg: this.leg, isPet: this.#isPet };
  10. }
  11. //静态方法
  12. static eat() {
  13. return "food";
  14. }
  15. //静态属性
  16. static nature = "creature";
  17. //私有属性
  18. #isPet = false;
  19. //访问器方法 getter, setter
  20. get isPet() {
  21. return this.#isPet;
  22. }
  23. set isPet(value) {
  24. this.#isPet = value;
  25. }
  26. }
  27. const cat = new Animal("Cat", 4);
  28. const bird = new Animal("Bird", 2);
  29. console.log(cat.info());
  30. //{name: "Cat", leg: 4, isPet: false}
  31. console.log(bird.info());
  32. //{name: "Bird", leg: 2, isPet: false}
  33. console.log(`动物吃:${Animal.eat()}`);
  34. //动物吃:food
  35. console.log(`动物本身是:${Animal.nature}`);
  36. //动物本身是:creature
  37. console.log(`猫是宠物吗? ${cat.isPet}`);
  38. //猫是宠物吗? false
  39. cat.isPet = true;
  40. console.log(`猫是宠物吗? ${cat.isPet}`);
  41. //猫是宠物吗? true
  42. //继承
  43. class Dog extends Animal {
  44. //继承
  45. //第一步必须执行父类构造方法,否则无法使用this
  46. constructor(name, type) {
  47. super(name, 4);
  48. //新成员初始化
  49. this.type = type;
  50. }
  51. info() {
  52. return { name: this.name, leg: this.leg, type: this.type };
  53. }
  54. //父类的私有属性不会被继承
  55. }
  56. const dog = new Dog("Dog", "哈士奇");
  57. console.log(dog.info());
  58. //{name: "Dog", leg: 4, type: "哈士奇"}
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