欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

JS知识点合集

程序员文章站 2024-03-05 18:44:19
...

JS知识点合集

作用域和作用域链

作用域
当函数在执行前,会创建函数执行期上下文对象,它定义了函数执行时的环境,我们将其理解为作用域。

一般作用域区分为

  1. 全局作用域
    如在script标签中定义的变量,它可以在全局被访问,其所处的环境即全局作用域
  2. 函数/局部作用域
    在函数内部定义的变量,不能在外部被访问到,其所处环境为函数作用域

作用域链
函数有一个scoped属性,存放着作用域的集合,该集合程链式结构,我们将其成为作用域链。

原型

函数的一个属性,定义了由构造函数实例化出的对象的公共祖先

function Person() {}
Person.prototype.height = 180;
var person = new Person();
// 可访问person .height

实例的__proto__属性指向了构造函数的原型。它们的关系如下

构造函数的原型属性Person.prototype
JS知识点合集
实例化对象、构造函数、原型的关系
JS知识点合集
原型存在一个属性constructor指向构造函数,同理实例化的对象也可以访问到这个属性
JS知识点合集
原型Person.prototype也有自己的原型
JS知识点合集
原型链的终点为null,原型组成的链状结构就是原型链,也就是这条蓝线

参考
由于原型的存在,实例可以访问到原型上的属性和方法,可用于实现继承

闭包

函数执行时,内部的函数被保存到了外部,从而使得函数执行期上下文(作用域)不被销毁,可以从外部访问到函数内部定义的变量。
由于闭包会使得函数的作用域不被释放,若使用不当会导致内存泄漏。
闭包的用途:
主要用途就两个:

1、将变量保存在内存中,不被销毁
私有化属性:

function onePerson() {
   let name = "";
   return {
       setName(newName) {
           name = newName
       },
       getName() {
           return name;
       }
   }
}
const p1 = onePerson();
p1.setName("xiaoming");
p1.getName(); // xiaoming

累加器:

function Calculator() {
   let num = 0;
   return {
       add() {
           num++;
       },
       get() {
           return num
       }
   }
}
const c1 = Calculator();
c1.add();
c1.get(); // 1
const c2 = Calculator();
c2.get(); // 0

2、模拟块级作用域
在 ES6 之前,是没有块级作用域的概念的,变量只有全局作用域和函数作用域。ES6 可以使用 let 关键字来实现块级作用域,变量的作用域在代码块中({})。

先写一个函数

function test1() {
    for(var i = 0; i < 10; i++) {
        setTimeout(() => {
          console.log(i);
        }, 0)
    }
}
test1();

由于异步任务执行时变量i的值已经变成10了,最后执行结果是10个10
可以用es6的let,或者闭包

function test2() {
    for(var i = 0; i < 10; i++) {
        setTimeout((function (j) {
            return () => console.log(j)
        }(i)))
    }
}
test2();

当然也可以这么写

function test2() {
    for (var i = 0; i < 10; i++) {
        (function (j) {
            setTimeout(() => {
                console.log(j);
            }, 0)
        }(i))
    }
}
test2();
相关标签: 前端重点知识