Maison > Article > interface Web > Variables JavaScript, portée et astuces memory_javascript
La nature des variables JS est de type lâche (pas de type forcé), ce qui détermine qu'il s'agit simplement d'un nom utilisé pour enregistrer une valeur spécifique à un moment précis ;
Puisqu'il n'y a pas de règles définissant le type de données qu'une variable doit contenir, la valeur de la variable et son type de données peuvent changer au cours du cycle de vie du script ;
1 Variables et portée
1.Types de base et types de référence
//Les variables JS contiennent des valeurs de deux types de données différents : les valeurs de type de base et les valeurs de type de référence ;
// 1. Valeur de type de base : un simple segment de données stocké dans la mémoire de la pile ; c'est-à-dire que cette valeur est entièrement stockée dans un emplacement de la mémoire
;
// Les valeurs de type de base incluent : Undefined|Null|Boolean|Number|String;
// Ces types occupent une taille d'espace fixe en mémoire ; leurs valeurs sont stockées dans l'espace de la pile, et on y accède par valeur
// 2. Valeur de type référence : un objet stocké dans la mémoire du tas (peut être composé de plusieurs valeurs), c'est-à-dire que ce qui est stocké dans la variable n'est en fait qu'un pointeur, qui pointe vers un autre emplacement dans la mémoire . Enregistrer l'objet ;
// La taille de la valeur du type référence n'est pas fixe, elle ne peut donc pas être enregistrée dans la mémoire de la pile et doit être enregistrée dans la mémoire tas ; mais l'adresse mémoire de la valeur du type référence peut être enregistrée dans la mémoire de la pile
// Lors de l'interrogation d'une variable de type référence, lisez d'abord l'adresse mémoire dans la mémoire de pile, puis recherchez la valeur dans la mémoire tas via l'adresse ;=>Accès par référence;
2.Attributs dynamiques
// 定义基本类型值和引用类型值的方式相似:创建一个变量并为该变量赋值; // 但当这个值保存到变量中以后,对不同类型值可以执行的操作则不一样; var box = new Object(); // 创建引用类型; box.name = 'lee'; // 新增一个属性; console.log(box.name); // =>lee; var box = 'lee'; // 创建基本类型 box.age = 15; // 给基本类型添加属性; console.log(box.age); // =>undefined;
3. Copier la valeur de la variable
// 在变量复制方面,基本类型和引用类型也有所不同; // 基本类型赋值的是值本身; var box = 'lee'; // 在栈内存中生成一个box'lee'; var box2 = box; // 在栈内存中再生成一个box2'lee'; // box和box2完全独立;两个变量分别操作时互不影响; // 引用类型赋值的是地址; var box = new Object(); // 创建一个引用类型;box在栈内存中;而Object在堆内存中; box.name = 'lee'; // 新增一个属性; var box2 = box; // 把引用地址赋值给box2;box2在栈内存中; // box2=box,因为它们指向的是同一个对象; // 如果这个对象中的name属性被修改了,box.name和box2.name输出的值都会被修改掉;
4. Paramètres de réussite
// JS中所有函数的参数都是按值传递的,即参数不会按引用传递; function box(num){ // 按值传递,传递的参数是基本类型; num +=10; // 这里的num是局部变量,全局无效; return num; } var num = 50; var result = box(num); console.log(result); // 60; console.log(num); // 50; function box(num){ return num; } console.log(num); // num is not defined; function box(obj){ obj.name = 'lee'; var obj = new Object(); // 函数内部又创建了一个对象,它是局部变量;但在函数结束时被销毁了; obj.name = 'Mr'; // 并没有替换掉原来的obj; } var p = new Object(); box(p); // 变量p被传递到box()函数中之后就被复制给了obj;在函数内部,obj和p访问的是同一个对象; console.log(p.name); // =>lee; // JS函数的参数都将是局部变量;也就是说,没有按引用传递;
5.Type de détection
// 要检测一个变量的类型,通过typeof运算符类判断; // 多用来检测基本类型; var box = 'lee'; console.log(typeof box); // =>string; // 要检测变量是什么类型的对象,通过instanceof运算符来查看; var box = [1,2,3]; console.log(box instanceof Array); // =>true; var box2 = {}; console.log(box2 instanceof Object); var box3 = /g/; console.lgo(box3 instanceof RegExp); var box4 = new String('lee'); console.log(box4 instanceof String); // =>true;是否是字符串对象; var box5 = 'string'; console.log(box5 instanceof String); // =>false; // 当使用instanceof检查基本类型的值时,它会返回false;
6. Environnement et portée d'exécution
// 执行环境:定义了变量或函数有权访问的其他数据,决定了它们各自的行为; // 在Web浏览器中,全局执行环境=window对象; // 因此所有的全局变量和函数都是作为window对象的属性和方法创建的; var box = 'blue'; // 声明一个全局变量; function setBox(){ console.log(box); // 全局变量可以在函数里访问; } setBox(); // 执行函数; // 全局的变量=window对象的属性; // 全局的函数=window对象的方法; // PS:当执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁; // 如果是在全局环境下,需要程序执行完毕,或者网页被关闭才会销毁; // PS:每个执行环境都有一个与之关联的变量对象,就好比全局的window可以调用全局变量和全局方法一样; // 局部的环境也有一个类似window的变量对象,环境中定义的所有变量和函数都保存在这个对象中; // (我们无法访问这个变量对象,但解析器会处理数据时后台使用它); var box = 'blue'; function setBox(){ var box = 'red'; // 这里是局部变量,在当前函数体内的值是'red';出了函数体就不被认知; console.log(box); } setBox(); console.log(box); // 通过传参可以替换函数体内的局部变量,但作用域仅限在函数体内这个局部环境; var box = 'blue'; function setBox(box){ // 通过传参,将局部变量替换成了全局变量; alert(box); // 此时box的值是外部调用时传入的参数;=>red; } setBox('red'); alert(box); // 如果函数体内还包含着函数,只有这个内函数才可以访问外一层的函数的变量; // 内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数; var box = 'blue'; function setBox(){ function setColor(){ var b = 'orange'; alert(box); alert(b); } setColor(); // setColor()的执行环境在setBox()内; } setBox(); // PS:每个函数被调用时都会创建自己的执行环境;当执行到这个函数时,函数的环境就会被推到环境栈中去执行,而执行后又在环境栈中弹出(退出),把控制权交给上一级的执行环境; // PS:当代码在一个环境中执行时,就会形成一种叫做作用域链的东西;它的用途是保证对执行环境中有访问权限的变量和函数进行有序访问;作用域链的前端,就是执行环境的变量对象;
7. Étendre la chaîne de portée
// 有些语句可以在作用域链的前端临时增加一个变量对象,该变量对象会在代码执行后被移除; // with语句和try-catch语句;这两个语句都会在作用域链的前端添加一个变量对象; // with语句:会将指定的对象添加到作用域链中; // catch语句:会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明; function buildUrl(){ var qs = '?debug=true'; with(location){ // with语句接收的是location对象,因此变量对象中就包含了location对象的所有属性和方法; var url = href+qs; // 而这个变量对象被添加到了作用域链的前端; }; return url; }
8. Aucune portée au niveau du bloc
// 块级作用域:表示诸如if语句等有花括号封闭的代码块,所以,支持条件判断来定义变量; if(true){ // if语句代码块没有局部作用域; var box = 'lee'; // 变量声明会将变量添加到当前的执行环境(在这里是全局环境); } alert(box); for(var i=0; i<10; i++){ // 创建的变量i即使在for循环执行结束后,也依旧会存在与循环外部的执行环境中; var box = 'lee'; } alert(i); alert(box); function box(num1,num2){ var sum = num1+num2; // 此时sum是局部变量;如果去掉var,sum就是全局变量了; return sum; } alert(box(10,10)); alert(sum); // sum is not defined;访问不到sum; // PS:不建议不使用var就初始化变量,因为这种方法会导致各种意外发生; // 一般确定变量都是通过搜索来确定该标识符实际代表什么;搜索方式:向上逐级查询; var box = 'blue'; function getBox(){ return box; // 此时box是全局变量;如果是var box='red',那就变成局部变量了; } alert(getBox()); // 调用getBox()时会引用变量box; // 首先,搜索getBox()的变量对象,查找名为box的标识符; // 然后,搜索继续下一个变量对象(全局环境的变量对象),找到了box标识符; // PS:变量查询中,访问局部变量要比全局变量更快,因为不需要向上搜索作用域链;
2 Problème de mémoire
// JS具有自动垃圾收集机制,执行环境会负责管理代码执行过程中使用的内存;它会自行管理内存分配及无用内存的回收; // JS最常用的垃圾收集方式就是标记清除;垃圾收集器会在运行的时候给存储在内存中的变量加上标记; // 然后,它会去掉环境中正在使用的变量的标记,而没有被去掉标记的变量将被视为准备删除的变量; // 最后,垃圾收集器完成内存清理工作,销毁那些标记的值并回收他们所占用的内存空间; // 垃圾收集器是周期性运行的,这样会导致整个程序的性能问题; // 比如IE7以前的版本,他的垃圾收集器是根据内存分配量运行的,比如256个变量就开始运行垃圾收集器,这样就不得不频繁地运行,从而降低了性能; // 一般来说,确保占用最少的内存可以让页面获得更好的性能; // 最佳方案:一旦数据不再使用,将其值设置为null来释放引用,这个做法叫做解除引用; var o = { name:'lee'; }; o = null; // 解除对象引用,等待垃圾收集器回收;
3 Résumé
// Les variables JS peuvent enregistrer deux types de valeurs : les valeurs de type de base et les valeurs de type de référence elles ont les caractéristiques suivantes :
// 1. Les valeurs de type de base occupent une taille fixe d'espace en mémoire, elles sont donc stockées dans la mémoire de la pile
;
// 2. Copier une valeur de type de base d'une variable vers une autre variable créera une copie de cette valeur
;
// 3. La valeur du type référence est un objet et est stockée dans la mémoire tas
;
// 4. Une variable contenant une valeur de type référence ne contient en réalité pas l'objet lui-même, mais un pointeur vers l'objet
;
// 5. Copiez une valeur de type référence d'une variable vers une autre variable. Ce qui est copié est en fait un pointeur, donc les deux variables finissent par pointer vers un objet
.
// 6. Pour déterminer le type de base d'une valeur, vous pouvez utiliser l'opérateur typeof ; et pour déterminer le type de référence d'une valeur, vous pouvez utiliser l'opérateur instanceof
.
// Toutes les variables existent dans un environnement d'exécution (scope). Cet environnement d'exécution détermine le cycle de vie des variables et quelle partie du code peut accéder aux variables ;
// 1. L'environnement d'exécution est divisé en environnement d'exécution global et environnement d'exécution de fonctions
;
// 2. Chaque fois que vous entrez dans un nouvel environnement d'exécution, une chaîne de portée pour rechercher des variables et des fonctions sera créée
;
// 3. L'environnement local d'une fonction a non seulement le droit d'accéder aux variables dans la portée de la fonction, mais a également le droit d'accéder à son environnement parent et même à l'environnement global
;
// 4. L'environnement d'exécution de la variable permet de déterminer si la mémoire doit être libérée de manière appropriée
;
3. Mémoire
// 1. Les valeurs quittant le périmètre seront automatiquement marquées comme recyclables et seront donc supprimées lors du garbage collection
;
// 2. Afin de garantir un recyclage efficace de la mémoire, les objets globaux/attributs d'objet globaux et les variables de référence circulaires qui ne sont plus utilisées doivent être publiés en temps opportun
;