javascript基础知识讲解
本篇适合javascript新手或者学了前端一段时间,对js概念不清晰的同学~~。
学习目的
本文针对javascript基础薄弱的同学,可以加深对javascript的理解。
本文将讲述以下几点对于初学者开说javascript(有的是大部分语言都有的)的坑
讲解内容如下:
1.连等
2.i++
3.包装对象
4.引用类型
5.&&与||
讲解部分
1.连等
小试牛刀
连等是常见的表达式,但是并不是所有情况都适合连等,连等只适用于字面量并不适用于引用类型。
//字面量连等得到想要的结果 vara,b; a=b=2; a//2 b//2 //引用类型连等不可预测 vararr1,arr2; arr1=arr2=[] arr1[0]=10 arr2[0]//10 //引用类型连等使得两个引用指向一个对象,操作其中一个,两个值都变
以上代码是常见的连等,有时候我们需要两个变量同赋值为一个值,我们就这样来操作,但是,如果是引用类型可不能连等赋值哦。
此外,连等赋值会有一个很大的漏洞,就是会将变量泄露到全局中去,上面代码我们没有将其泄露,但看下面代码:
functionfn(num){ vara=b=num; a//num b//num } fn(10) a//报错 b//10 //我们并不没有定义全局变量b
可以看到,我们执行了fn函数后,全局作用域中出现了b变量,这是为什么?看vara=b=num这句话,这句话可以分成两句来看
vara a=b=num //只声明了a
我们其实只声明了a变量,连等的b并没有声明,由此可以知道,b被挂在了全局的window对象上,造成了变量泄露到了全局。
初出茅庐
上面只是简单的例子,接下来我们看一个复杂点的例子
vara={x:1} varb=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(查找)。
下面,就上面例子,我们来演示一下引擎的工作流程
vara={x:1} //引擎:我将要对a变量LHS(赋值),内容是{x:1} //作用域:刚声明了a变量,给你。 varb=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.++操作符
大家最很常用++操作符,其实也没什么很大奇特之处,但是对于新手入门的你是否真正了解他。
vara=1; varb=a++ a//2 b//1 varc=1; vard=++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.包装对象
我们在用字符串获取长度、使用方法截取等行为时,你有没有想过:字面值只是个值,为什么他会有方法属性,不是应该对象才有的吗?的确是对象才有的,但是在执行表达式时,产生了包装对象。也许你看过了此知识点,可以跳过。
varstr='hello' str.length//5 str.aaa=5 str.aaa//undefined
我们定义一个str字符串,获取长度为5,但是我们自己加一个属性aaa缺获取不到,这需要用包装对象的声明周期来解答:包装对象的声明周期只存在于一个表达式内
varstr='hello' str.length //等价于 newString(str).length str.aaa=5 //等价于 newString(str).aaa=5 str.aaa //等价于 newString(str).aaa
也就是说,每一次用到str属性时,都是先包装成String对象,操作完后,对象释放,可见,以上两次str.aaa是不同的对象,所以第二次获取aaa属性当然没有了。不了解可以百度一下js包装对象,有详细的解答。
4.引用类型
大部分语言都有引用类型,其实就是对象变量。c语言中,我们将引用类型理解为指针,这个指针是动态指向一块内存,通过代码的变化,指针的指向会随之改变。js也一样。
在我们书写代码中,一定要记住引用类型变量和字面值变量的区别,他们分别有不同的用处。
varglobal=newObject() functionsetColor(obj){ obj.color='blue' obj=newObject() 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判断,如:
vara=2; varb=false if(a&&b){ alert('best') } if(a||b){ alret('good')//运行 }
他们的用法不局限于判断左右两边的&&和||关系,还可以用来提供代码的质量
varobj={} 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基础本章简单的介绍在这里,内容并不全面,还请多多见谅。如有错误,请指出。。。。
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,同时也希望多多支持毛票票!