前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >闰土说JS进阶之变量

闰土说JS进阶之变量

作者头像
闰土大叔
发布2018-04-12 11:00:13
7700
发布2018-04-12 11:00:13
举报
文章被收录于专栏:闰土大叔

前言

前端世界如此喧嚣,能进阶的何其稀少。大家好,你们的闰土哥在沉寂了数月之后又回来了!(此处应有掌声~~~)

前段时间在群里关于“闰土去哪儿了”的话题,让我既欣喜又尴尬。欣喜的是大家还记得我,尴尬的是我竟不知道该如何回复。原因有二,一是我换了家公司继续撸代码,二是那段时间我沉淀了一下自己的技术和生活。闰土这次回来是带着满满的干货想与大家分享,如果你在这里能学到一点点知识,收获一丝丝感悟,那闰土便知足了。(YY:按照惯例,此刻该听到搬小板凳的声音了,嘻嘻~)

正文

开门见山,这次闰土要讲讲JavaScript进阶。废话不多说,先拿变量开刀。

在我们前端日常的JavaScript编码中,总避免不了声明变量。那变量是什么呢?我们前端人员都知道,变量其实就是一个容器,用来存放各种不同的数据类型的值,包括基本类型值和引用类型值。基本类型值有五种,参加过前端面试的人想必都能倒背如流,分别是Undefined、Null、Boolean、Number和String。

定义基本类型值和引用类型值的方式是类似的,就是创建一个变量并为该变量赋值。先来看看下面的栗子:

代码语言:javascript
复制
var person = new Object();

person.name = 'runtu';
console.log(person.name);   // "runtu"

在上面的例子中我们创建了一个对象并将其保存在了变量 person 中。然后,我们为该对象添加了一个名为 name 的属性,并将字符串值“runtu”赋给了这个属性。紧接着,又通过console.log()函数访问了这个新属性。如果person这个对象不被销毁或者这个属性不被删除,那么这个属性将一直存在。

也就是说,对于引用类型的值,我们可以为其添加/修改/删除属性和方法,但是我们不能给基本类型的值添加属性,尽管这样做不会导致任何错误(我们建议不这么写,因为写了也没用 Orz)。

接下来我们再聊聊复制变量值。

先来看看下面的栗子:

代码语言:javascript
复制
var age1 = 26;

var age2 = age1;

在以上代码中,age1中保存的值是26,是基本类型值。当使用age1的值来初始化age2时,age2中也保存了值26,但该值只是age1的一个副本,所以,这两个变量可以参与此后任何操作而不会相互影响。

看完了复制基本类型值,我们再来看下一个栗子:

代码语言:javascript
复制
var person1 = new Object();

var person2 = person1;
person1.name = 'runtu';
console.log(person2.name);  // "runtu"

在这里,变量person1保存了一个对象的新实例。然后这个值被复制到了person2;换句话说,person1和person2都指向同一个对象。这样一来,当为person1添加name属性后,person2也可以访问到这个属性。

到这里,我们就可以适当的总结一下,当一个变量复制另一个变量的引用类型值时,这个值的副本其实是一个指针,而这个指针则指向存储在堆中的一个对象。复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响到另一个变量。

接下来我们讲讲传递参数,重点来了,该划重点的划下,这是必考题

函数传参,相信很多前端老司机都已经耳熟能详了,可能更多的前端新人小白们还是懵懵懂懂的,这里我说下。在ECMAScript中所有函数的参数都是按值传递的,也就是说,把函数外部的值复制给函数内部的参数,就和把值从一个变量复制到另一个变量一样,原理是一样的。

接下来这句话可能有点绕,基本类型值的传递和基本类型变量的复制一样,同样的,引用类型值的传递和引用类型变量的复制是一样的。有不少工作了两三年的前端er在这个点上可能也会感到困惑。为什么呢?这个知识点可能比较晦涩难懂,因为像咱们平时访问变量有按值和按引用这两种方式,而参数只能按值传递。照样举个栗子:

代码语言:javascript
复制
function addSix(num){
    num += 6;

    return num;

}

var count = 20;

var result = addSix(count);

console.log(count);  // 20,没有变化
console.log(result);  // 26(有没有感觉这个数字出现频率较高,嘻嘻~)

这里的函数addSix()有一个参数num,而参数实际上是函数的局部变量。在调用这个函数时,变量count作为参数被传递给函数,于是数值20被复制给参数num。在函数内部,参数num的值被加上了6,但是这一变化不会影响外部的count变量,参数num和变量count素昧平生互不相识。假如num是按引用传递的话,那么变量count的值也将变成30,从而反映函数内部的修改。

当然使用数值等基本类型值来说明按值传递参数比较简单,但如果使用对象,那么问题就不那么浅显易懂了。闰土再举一个栗子:

代码语言:javascript
复制
function setName(obj){
    obj.name = 'runtu';

    obj = new Object();

    obj.name = 'shaonian';

}

var person = new Object();

setName(person);
console.log(person.name);  // runtu

有小白会问:console出来的怎么不是 “shaonian” 呢?

这是一个很经典的问题,你想如果person是按引用传递的,那么person就会被自动修改为指向其name属性值为“shaonian”的新对象。但是,重点来了。当接下来再访问person.name时,显示的值仍然是“runtu”。这说明即使在函数内部修改了参数的值,但原始的引用仍然保持不变。实际上当在函数内部重写obj时,这个变量引用的就是一个局部对象了。而这个局部对象会在函数执行完毕后立即被销毁。

所以,结论就是,所有的函数传参都是按值传递的。(又该划重点了,咳~咳~)

备注:本文参考红宝书,如有雷同,纯属拷贝。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2017-10-26,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 闰土大叔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档