理解JavaScript变量和类型

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

内容简介: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秘密花园


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

查看所有标签

猜你喜欢:

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

爆裂

爆裂

[美] 伊藤穰一、[美] 杰夫·豪 / 张培、吴建英、周卓斌 / 中信出版集团 / 2017-9-1 / 65.00元

越是在发生重大改变的时刻,越是会出现两极分化,赢家、输家有时只在一念间。未来已经装上了全新的操作系统。这是一个重大升级,对我们而言,随之而来的则是陡峭的学习曲线。在指数时代,替换旧逻辑,我们的思维亟需与世界对接,推翻过去已经成为大众所接受的常识,学会差异化思考才能屹立不倒,不被卷入历史的洪流。 在《爆裂》一书中,伊藤穰一和杰夫·豪将这一逻辑提炼为9大原则,帮助人们驾驭这一动荡时刻,应对当下的......一起来看看 《爆裂》 这本书的介绍吧!

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具