javascript基础知识讲解


Posted in Javascript onJanuary 11, 2017

本篇适合javascript新手或者学了前端一段时间,对js概念不清晰的同学~~。

学习目的

本文针对javascript基础薄弱的同学,可以加深对javascript的理解。

本文将讲述以下几点对于初学者开说javascript(有的是大部分语言都有的)的坑

讲解内容如下:

1. 连等

2. i++

3. 包装对象

4. 引用类型

5. && 与 ||

讲解部分

1. 连等

小试牛刀

连等是常见的表达式,但是并不是所有情况都适合连等,连等只适用于字面量并不适用于引用类型

// 字面量连等得到想要的结果
var a,b;
a = b = 2;
a // 2
b // 2
// 引用类型连等不可预测
var arr1, arr2;
arr1 = arr2 = []
arr1[0] = 10
arr2[0] // 10
//引用类型连等使得两个引用指向一个对象,操作其中一个,两个值都变

以上代码是常见的连等,有时候我们需要两个变量同赋值为一个值,我们就这样来操作,但是,如果是引用类型可不能连等赋值哦。

此外,连等赋值会有一个很大的漏洞,就是会将变量泄露到全局中去,上面代码我们没有将其泄露,但看下面代码:

function fn (num) {
 var a = b = num;
 a // num
 b // num
}
fn(10)
a // 报错
b // 10
// 我们并不没有定义全局变量b

可以看到,我们执行了fn函数后,全局作用域中出现了b变量,这是为什么?看 var a = b = num这句话,这句话可以分成两句来看

var a
a = b = num
//只声明了a

我们其实只声明了a变量,连等的b并没有声明,由此可以知道,b被挂在了全局的window对象上,造成了变量泄露到了全局。

初出茅庐

上面只是简单的例子,接下来我们看一个复杂点的例子

var a = {x: 1}
var b = a
a.x = a = {y: 1}
a.x // undefined
b.x // {y: 1}

这个例子是在一个测试题中看到的,乍一看,好像不明觉厉,但是一点都不难理解。

1. a 和 b是引用了类型,同指向了一个对象 {x: 1}

2. a.x 引用了原对象的x属性, a 则为一个引用变量

3. a  = {y: 1}  只是将a这个引用变量的指针指向了另一个对象{y: 1}

4. a.x = a,前者还是代表着原来的对象的x属性,也就是b引用的对象的x属性

5. 赋值完毕。

可能你还没有理解,不要急,下面我们将解剖javascript引擎让你懂的明明白白

庖丁解牛

引擎的工作原理: 引擎在解析javascript表达式时,会进行LHS查询, RHS查询(详见《你不知道的javascript》),我将它们理解为LHS(赋值),RHS(查找)。

下面,就上面例子,我们来演示一下引擎的工作流程

var a = {x: 1}
// 引擎:我将要对a变量LHS(赋值),内容是{x: 1}
// 作用域: 刚声明了a变量,给你。
var b = a
// 引擎: 我将要对a变量RHS(查找)
// 作用域: 你刚刚给它LHS了,给你吧
// 引擎: 我将要对b变量LHS(赋值),内容为a变量指向的对象
// 作用域:刚声明了b变量,给你。
a.x = a = {y: 1}
// 引擎:我将要对a进行LHS(赋值),内容是另一个对象{y:1}
// 作用域:可以,给你,但好像还有其他命令,先不要赋值。
// 引擎: 是的,下一步我还需要对a.x 进行LHS(赋值),内容是将要改变的a变量
// 作用域: 可以,a变量指向的对象有x属性,不过马上a就改变了,不过没关系,b变量也指向那个对象,赋值完后,你可以用b变量引用旧对象。
// 引擎:了解了,我先把a变量赋值为一个新的对象,然后把原来的a变量指向的对象的x属性赋值为 新a。
a.x // undefined
// 引擎: 我需要拿到a变量指向的对象的x属性
// 作用域: 你刚刚改变了a的指向,现在的a指向的对象已经没有x属性了
b.x // {y: 1}
// 引擎: 我需要拿到b变量指向的对象的x属性
// 作用域: 你是想拿到你旧对象的x属性吧,给你,不过已经被你在之前改变了值,现在b.x的值就是a指向的新对象的值。

以上是我的理解,没有权威认证。想详细了解执行过程,请参考《你不知道的javascript》,如果本节有误,请指出。

2. ++操作符

大家最很常用 ++ 操作符,其实也没什么很大奇特之处,但是对于新手入门的你是否真正了解他。

var a = 1;
var b = a++
a // 2
b // 1
var c = 1;
var d = ++ c;
c // 2
d // 2

前++和后++,一个是返回表达式自增后一个是返回表达式自增前的值。我们可以把两个进行分解,看一下过程。

b = a++
// 等价于 ...
b = a
a = a + 1
//.........................
b = ++ a
// 等价于 ...
a = a + 1
b = a

只是一个运算顺序问题,这个可能好理解,但是也有一个坑,如下。

前几天一个人问: 1++ 等于几?答: 2

估计很多人第一反应就是2,但是这大错特错!那为什么不等于2呢,其实 1++是报错了,并不是合法的表达式,原因如下:

1 ++
// 等价于
1 = 1 + 1
// 引擎对 1 进行LHS(赋值),作用域发现他是非法变量,所以会报错 左值无效。

3. 包装对象

我们在用字符串获取长度、使用方法截取等行为时,你有没有想过: 字面值只是个值,为什么他会有方法属性,不是应该对象才有的吗?的确是对象才有的,但是在执行表达式时,产生了包装对象。也许你看过了此知识点,可以跳过。

var str = 'hello'
str.length // 5
str.aaa = 5
str.aaa // undefined

我们定义一个str字符串,获取长度为5,但是我们自己加一个属性aaa缺获取不到,这需要用包装对象的声明周期来解答:包装对象的声明周期只存在于一个表达式内

var str = 'hello'
str.length
// 等价于
new String(str).length
str.aaa = 5
//等价于
new String(str).aaa = 5
str.aaa
// 等价于
new String(str).aaa

也就是说,每一次用到str属性时,都是先包装成String对象,操作完后,对象释放,可见,以上两次str.aaa是不同的对象,所以第二次获取aaa属性当然没有了。不了解可以百度一下js包装对象,有详细的解答。

4. 引用类型

大部分语言都有引用类型,其实就是对象变量。c语言中,我们将引用类型理解为指针,这个指针是动态指向一块内存,通过代码的变化,指针的指向会随之改变。js也一样。

在我们书写代码中,一定要记住引用类型变量和字面值变量的 区别,他们分别有不同的用处。

var global = new Object()
function setColor (obj) {
 obj.color = 'blue'
 obj = new Object()
 obj.color = 'red'
}
setColor(global)
global.color // blue

这是《javascript高级程序设计》里面的一个例子,我们传递一个对象global到setColor函数里,在内部进行了如上操作,我们打印出global.color是blue,为什么不是red?这里就是引用类型的结果。

1. global变量是引用类型,他指向一个对象,

2. 传递到setColor函数中,obj就引用了global指向的对象(下面称为globalObj)

3. 给globalObj赋值一个color属性为blue字符串,这时global.color是blue了

4. 将obj指向另一个新对象localObj,使得obj与global断开连接。

5. 将localObj.color赋值为‘red'

可以看出,我们并没有对global对象的color进行'red'赋值,'red'赋值给了另一个对象的color属性。

结论:引用类型传递是将两个变量指向同一个对象,而字面量的传递仅仅是值的赋值传递。我们可以将引用类型传递到函数进行改变,不可以在函数内改变传递进来的字面值。

5. && 与 ||

两者的基本运用相信大家都了解,大部分用来if判断,如:

var a = 2;
var b = false
if (a && b) {

 alert('best')
}
if (a || b) {
 alret('good')  // 运行
}

他们的用法不局限于判断 左右两边的 && 和 || 关系,还可以用来提供代码的质量

var obj = {}
if (obj.info.user === 'xu') { // terrible
 // ..
}
if (obj.info && obj.info.user === 'xu' ) { // good
 // ... 
}

如果仅仅判断obj.info.user 会报错造成程序终止,但是下面那样判断就大使得代码健壮,不会那么容易崩溃。

重点: && 和 || 并不会返回true和false,他会返回终止此表达式的那个变量值。

true && 6 // 6
NaN && false // NaN
'0' || 6 // '0'
false || true // true
false || 0 && 1 // 0
false || 1 && 0 // 0

&&和||, &&优先级大于||。

&&操作符,如果左边为假,返回左边值,否则,始终返回右边值

||操作符,如果左边为真,返回左边值, 否则,始终返回右边值。

结尾

javascript基础本章简单的介绍在这里,内容并不全面,还请多多见谅。如有错误,请指出。。。。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持三水点靠木!

Javascript 相关文章推荐
用js判断用户浏览器是否是XP SP2的IE6
Mar 08 Javascript
javascript实现的listview效果
Apr 28 Javascript
在IE6下发生Internet Explorer cannot open the Internet site错误
Jun 21 Javascript
浅谈Javascript 执行顺序
Dec 18 Javascript
javascript实现在指定元素中垂直水平居中
Sep 13 Javascript
jQuery控制DIV层实现由大到小,由远及近动画变化效果
Oct 09 Javascript
js密码强度检测
Jan 07 Javascript
AngularJs IE Compatibility 兼容老版本IE
Sep 01 Javascript
微信小程序 生命周期详解
Oct 12 Javascript
jQuery Pagination分页插件使用方法详解
Feb 28 Javascript
Vue Ajax跨域请求实例详解
Jun 20 Javascript
vue 的keep-alive缓存功能的实现
Mar 22 Javascript
bootstrap侧边栏圆点导航
Jan 11 #Javascript
微信小程序开发(二)图片上传+服务端接收详解
Jan 11 #Javascript
JavaScript BASE64算法实现(完美解决中文乱码)
Jan 10 #Javascript
使用vue实现点击按钮滑出面板的实现代码
Jan 10 #Javascript
Mac下使用charles遇到的问题以及解决办法
Jan 10 #Javascript
vue2滚动条加载更多数据实现代码
Jan 10 #Javascript
简单实现IONIC购物车功能
Jan 10 #Javascript
You might like
【动漫杂谈】关于《请在T台上微笑》
2020/03/03 日漫
PHP 创建文件(文件夹)以及目录操作代码
2010/03/04 PHP
PHP is_dir() 判断给定文件名是否是一个目录
2010/05/10 PHP
destoon实现调用当前栏目分类及子分类和三级分类的方法
2014/08/21 PHP
javascript 对象定义方法 简单易学
2009/03/22 Javascript
javascript模拟select,jselect的方法实现
2012/11/08 Javascript
jQuery中bind(),live(),delegate(),on()绑定事件方法实例详解
2016/01/19 Javascript
MVC+jQuery.Ajax异步实现增删改查和分页
2020/12/22 Javascript
基于JS代码实现图片在页面中旋转效果
2016/06/16 Javascript
关于JavaScript限制字数的输入框的那些事
2016/08/14 Javascript
如何实现json数据可视化详解
2016/11/24 Javascript
从parcel.js打包出错到选择nvm的全部过程
2018/01/23 Javascript
JS实现获取进今年第几天是周几的方法分析
2018/06/27 Javascript
vue-cli 构建骨架屏的方法示例
2018/11/08 Javascript
封装微信小程序http拦截器过程解析
2019/08/13 Javascript
js 判断当前时间是否处于某个一个时间段内
2019/09/19 Javascript
nodejs实现聊天机器人功能
2019/09/19 NodeJs
基于vue实现图片验证码倒计时60s功能
2019/12/10 Javascript
vue 使用rules对表单字段进行校验的步骤
2020/12/25 Vue.js
[03:39]2015国际邀请赛主赛事首日精彩回顾
2015/08/05 DOTA
简单介绍Python中的len()函数的使用
2015/04/07 Python
Python自动扫雷实现方法
2015/07/25 Python
详解Django 中是否使用时区的区别
2018/06/14 Python
Python调用C++,通过Pybind11制作Python接口
2018/10/16 Python
Python实现图片转字符画的代码实例
2019/02/22 Python
ERLANG和PYTHON互通实现过程详解
2019/07/05 Python
Python split() 函数拆分字符串将字符串转化为列的方法
2019/07/16 Python
Python日志器使用方法及原理解析
2020/09/27 Python
详解HTML5新增标签
2017/11/27 HTML / CSS
电大学习个人自我评价范文
2013/10/04 职场文书
汽车检测与维修应届毕业生求职信
2013/10/19 职场文书
玩具公司的创业计划书
2013/12/31 职场文书
超市端午节活动方案
2014/01/23 职场文书
群众路线个人剖析材料及整改措施
2014/11/04 职场文书
redis通过6379端口无法连接服务器(redis-server.exe闪退)
2021/05/08 Redis
解决Pytorch半精度浮点型网络训练的问题
2021/05/24 Python