理解JavaScript变量和类型

栏目: JavaScript · 发布时间: 7年前

内容简介:ECMAScript标准规定了7种数据类型,这些数据类型分为1.1 原始类型局有不可变性:如下:

转载自ConardLi: 《【JS进阶】 你真的掌握变量和类型了吗》 公众号: code秘密花园

1. JavaScript数据类型

ECMAScript标准规定了7种数据类型,这些数据类型分为 原始类型对象类型

1.1 原始类型局有不可变性:

如下:

var str = 'abc';

str.slice(1);

str.substr(1);

str.trim(1);

str.toLowerCase(1);

str[0] = 1;

console.log(str); //abc

以上这些方法都在原字符串的基础上产生一个新字符串,而非直接去改变str,这印证了字符串的不可变形。

当执行以下代码时:

str += '6';

可见str的值被改变了,这貌似与字符串的不可变性不符合呀,这个要从内存上来理解。

在JavaScript中,每一个变量在内存中都需要一个空间来存储。

内存空间有分为栈内存和堆内存。

栈内存:

  • 存储的值大小固定
  • 空间较小
  • 可以直接操作其保存的变量,运行效率高
  • 由系统自动分配存储空间

JavaScript中的原始类型的值被直接存储在占中,在变量定义时,栈就为其分配好了内存空间。

理解JavaScript变量和类型

由于栈中的内存空间的大小是固定的,所以存储在栈中的变量就是不可变的。

而当执行了 str += '6' 的操作时,实际上是在栈中又开辟了一块内存空间用于存储‘abc6’,然后将变量str指向这块空间。

理解JavaScript变量和类型

1.2 引用类型

堆内存:

  • 存储的值大小不定,可动态调整
  • 空间较大,运行效率低
  • 无法直接操作其内部存储,使用引用地址读取
  • 通过代码进行分配空间

引用类型的值实际存储在堆内存中,它在栈中只存储了一个固定长度的地址,这个地址指向堆内存中的值。

如下:

var obj1 = {name: 'abc'};

var obj2 = {age: 18};

var obj3 = function() {...};

var obj4 = [1, 2, 3, 4, 5];

理解JavaScript变量和类型

引用类型不具有不可变性,可以改变它们:

obj1.name = 'abc6';

obj2.age = 19;

obj4.length = 0;

console.log(obj1); //{name: 'abc6'}

console.log(obj2); //{age: 19}

console.log(obj4); //[]

以数组为例,它的很多方法都可以改变它自身:

  • pop()
  • push()
  • shift()
  • unshift()
  • reverse()
  • sort()
  • splice()

1.3 复制

原始类型的复制:

var name = 'abc';

var name2 = name;

name2 = 'code';

console.log(name); //abc

理解JavaScript变量和类型

内存中有一个变量name,值为abc。从变量name复制出一个变量name2,此时在内存中创建了一个块新的空间用于存储abc,虽然两者的值是相同的,但是两者指向的内存空间完全不同,这两个变量参与任何操作都互不影响。

引用类型的复制:

var obj = {name: 'abc'};

var obj2 = obj;

obj2.name = 'code';

console.log(obj.name); //code

理解JavaScript变量和类型

当复制引用类型的变量时,实际上复制的是堆中存储的地址,所以复制出来的obj2实际上和obj指向的堆中同一个对象。因此,改变其中任何一个变量的值,两一个变量都会受到影响。

1.4 比较

当对两个变量进行比较时,不同类型的变量的表现是不同的:

var name = 'abc';

var name2 = 'abc';

console.log(name === name2); //true

var obj = {name: 'abc'};

var obj2 = {name: 'abc'};

console.log(obj === obj2); //false

对于原始类型,比较时会直接比较它们的值,如果值相等,即返回true。

对于引用类型,比较时会比较它们的引用地址,虽然两个变量在堆中存储的对象具有属性值都是相等的,但是它们被存储在了不同的存储空间,因此比较值为false。

1.5 值传递和引用传递

如下:

let name = 'abc';

function changeValue(name) {

name = 'code';

}

changeValue(name);

console.log(name);

执行上面的代码,如果最终打印出来的name是‘abc’,没有改变,说明函数参数传递的是变量的值,即值传递。如果最终打印出来的是‘code’,函数内部的操作可以改变传入的变量,那么说明函数参数传递的是引用,即引用传递。

上面的例子执行结果是‘abc’,即函数参数仅仅是被传入变量复制给了的一个局部变量。改变这个局部变量不会对外部变量产生影响。

let obj = {name: 'abc'};

function changeValue(obj) {

obj.name = 'code';

}

changeValue(obj);

console.log(obj.name); //code

ECMAScript中的所有的函数的参数都是按值传递的。

当函数参数是引用类型时,同样将参数复制了一个副本到局部变量,只不过复制的这个副本是指向堆内存中的地址而已,在函数内部对对象的属性进行操作,实际上和外部变量指向堆内存中的值相同,但是这并不代表这引用传递。

接着下一个例子:

let obj = {};

function changeValue(obj) {

obj.name = 'abc';

obj = {name: 'code'}; //赋予副本新的地址

}

changeValue(obj);

console.log(obj.name); //abc

可见,函数参数传递的并不是变量的引用,而是变量拷贝的副本,当变量是原始类型时,这个副本就是值本身,当变量是引用类型是,这个副本是指向堆内存的地址。

重要的事情说三遍:

  1. ECMAScript中的所有的函数的参数都是按值传递的。
  2. ECMAScript中的所有的函数的参数都是按值传递的。
  3. ECMAScript中的所有的函数的参数都是按值传递的。

转载自ConardLi: 《【JS进阶】 你真的掌握变量和类型了吗》 公众号: code秘密花园


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Ordering Disorder

Ordering Disorder

Khoi Vinh / New Riders Press / 2010-12-03 / USD 29.99

The grid has long been an invaluable tool for creating order out of chaos for designers of all kinds—from city planners to architects to typesetters and graphic artists. In recent years, web designers......一起来看看 《Ordering Disorder》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具