Javascript基础——Javascript语言核心(1):词法结构;类型、值和变量


写在前面

作为一个工作了6年的前端,犀牛书(《Javascript权威指南》)没有完整读过一遍,似乎很不合格。最近也被别人问到一些问题,心里总不太有把握。

现如今框架层出,但是永远最重要的还是基础。于是决定,将这本书读完,消化整理后,完成这份精简版的更利于记忆的基础系列笔记,给我自己以及需要提高javascript基础的小伙伴们。

为了方便查找对应的知识点详情,本系列沿用了犀牛书中的章节结构和标识,跳过了过于基础的内容。


词法结构

2.1 字符集

Javascript是区分大小写的语言。online,Online,onLine,OnLine是四个不同的变量名。

HMTL 不区分大小写

2.2 注释

Javascript支持两种注释,单行//和多行/**/

//这里是单行注释

/*
*这个是多行注释
*下一行
*/

2.3 直接量

直接量(literal)是程序中直接使用的数据值。下面是一些直接量的例子:

12             //数字
1.2            //小数
"hello"        //字符串
true           //布尔值
null           //空
/javascript/gi //正则表达式直接量

2.4 标识符和保留字

标识符

标识符用来对变量和函数进行命名。命名规则:

~字母数字_$
开头×
后续

允许标识符中出现Unicode字符全集中的字母和数字。

保留字

Javascript把一些标识符拿出来做关键字。因此这些不能再作为标识符(这里不详细列出保留字)。

2.5 可选的分号

使用;将语句分开。


类型、值和变量

3.1 数字

Javascript不区分整数值和浮点数值,所有数字均用浮点数值表示

3.1.3 算数运算

算数运算在溢出(overflow)、下溢(underflow)或被0整除都不会报错。会显示Infinity-Infinity来表示无穷大和负无穷大。如果像0/0没有意义,结果是非数字(not-a-number),显示NaN

1/0        //=> Infinity
-1/0       //=> -Infinity
0/0        //=> NaN
1/Infinity //=> 0

非数字值(NaN)有一点特殊:它和任何值都不相等,包括自身。

var x=0/0 //=> NaN
x==NaN    //=> false

两个函数isNaN()isFinite()判断是否非数字和有限数。

var x=0/0;
isNaN(x); //=> true
var y=1/0   //=> Infinite
isFinite(y) //=> false;
isFinite(5) //=> true;

正零和负零相等,正无穷大和负无穷大不等:

var x=0,y=-0;
x==y         //=> true
1/x==1/y     //=> false;
3.1.4 二进制浮点数和四舍五入错误

上面提到Javascript中所有数字均用浮点数值表示,而实数有无数个,但通过浮点数的形式只能表示有限个数。即,使用实数时,常常只是真实值的一个近似表示。

Javascript采用IEEE-754浮点数表示法,是一种二进制表示法,不能精确表示类似0.1这种十进制分数。

var x = .3 - .2; //=> 0.09999999999999998
var y = .2 - .1; //=> 0.1
x==y             //=> false

为避免该问题,在进行重要的金融计算时,使用大整数计算。用整数“分”,而非小数“元”进行基于货币单位的运算。

var x = 3 - 2; //=> 1
var y = 2 - 1; //=> 1
x==y           //=> true

3.2 文本

3.2.1 字符串直接量

字符串直接量是由''""括起来的字符序列。

ECMAScript 5中,字符串直接量可以拆分成数行,必须以反斜线\结束。

var myString1="<div>\
                <a>link</a>\
            </div>";
3.2.2 转义字符

常用的转义字符:

转义字符含义
\n换行符
\"双引号
\'单引号
\\反斜线
var str='Two\nLines'; 
//=> "Two
//   Lines"
3.2.3 字符串的使用

使用+进行字符串连接。

字符串的length属性和方法(indexOf, split等等)以及正则表达式后面再介绍。

3.3 布尔值

只有两个值:truefalse

任意Javascript的值都可以转换为布尔值,下列会转换成false

undefined
null
0
-0
NaN
""//空字符串

3.4 null和undefined

~描述类型(typeof)
null关键字,表示空值object
undefined值空缺,变量没有初始化undefined

如何区分这两个值?使用严格相等运算符===

null == undefined  //=> true
null === undefined //=> false

如果需要将“空”赋值给变量或属性或作为参数传入参数,使用null

3.6 包装对象

引例:

var str="hello";
str.length //=> 5

问:字符串不是对象,为什么会有属性?

答:将字符串值通过调用new String(str)的方式转换成对象,并继承了字符串的属性。

字符串、数字和布尔型的属性都是只读的,不能给他们定义新属性,是有别于对象的。

var s="test";
s.len=4;
var t = s.len; //=> undefined

可通过String(), Number()或Boolean()构造函数显式创建包装对象。他们和原始值不严格相等。

var s='test', n=1, b=true;

var S = new String(s);
var N = new Number(n);
var B = new Boolean(b);

S==s  //=> true
S===s //=> false

3.7 不可变的原始值和可变的对象引用

~类型描述比较
原始值undefined、null、布尔值、数字、字符串不会更改:任何方法都无法更改值相等则相等
对象数组、函数值可修改引用同一个基对象时,才相等;两个对象包含同样属性及值并不相等

原始值不会更改示例:

var str="hello";
str.toUpperCase(); //=> "HELLO"
str                //=> "hello"

对象比较示例:

var x={a:1},y={a:1};
x==y               //=> false: 两个单独的对象永不相等

var x=[],y=[];
x==y               //=> false: 两个单独数组永不相等

var x={},y=x;
x==y               //=> true: 引用相同

那么如何判断两个对象是否含有同样的属性呢?遍历。

function equalArrays(a,b){
    if(a.length != b.length){
        return false;
    }
    for(var i=0;i< a.length;i++){
        if(a[i] !=b[i]){
            return false;
        }
    }
    return true;
}

var x={a:1},y={a:1};
equalArrays(x,y);    //=> true: 属性值都相等

3.8 类型转换

Javascript中的取值非常灵活,会根据期望进行转换,例如:

2 + 1       //=> 3
"2" + 1     //=> "21"
"2" - "1"   //=> 1
"2" * "1"   //=> 2
"2" - "Hi"  //=> NaN
true + true //=> 2

下面这几个类型转换需要注意:

转换为数字
undefinedNaN
null0
“”(空字符串)0
true1
false0
3.8.1 转换与相等性

由于Javascript可以做灵活的类型转换,因此==相等运算符也会随相等的含义灵活多变。

"0" == 0     //=> true: 比较前[字符串]转成[数字]
0 == false   //=> true: 比较前[布尔值]转成[数字]
"0" == false //=> true: 比较前[字符串]和[布尔值]都转成[数字] 

===恒等运算符在判断相等时不做类型转换

注意:一个值转换为另一个值并不意味两值相等。

null == false      //=> false
undefined == false //=> false
3.8.2 显式类型转换
  • 显示类型转换方法

Boolean()Number()String()Object()

除了null和undefined之外任何值都具有toString()方法。

Number("5")   //=> 5
String(false) //=> "false" 或者使用 false.toString()
Boolean([])   //=> true, 注意Boolean("")是false
Object(3)     //=> new Number(3)
  • 隐式转换运算符
3 + "" //=> "3"   数字  -> 字符串
+"3"   //=> 3     字符串 -> 数字
!!("") //=> false 转成布尔型,相当于Boolean(""),注意是【双感叹号】
  • 数字与字符串转换方法

    • number-to-string

      toString()方法接受转换基数(radix)的可选参数。默认是十进制。

      var n= 10;
      n.toString(2) //=> "1010"
      n.toString(16) //=> "a"
    • string-to-number

      这三个方法都会四舍五入或填充0。

      函数名称作用参数含义默认情况
      toFixed()保留几位小数小数个数四舍五入为整数
      toExponential()使用指数计数法小数个数保留全部小数
      toPrecision()保留有效数字位数有效数字位数原值
      var n=12345.6789;
      
      n.toFixed()        //=> "12346"
      n.toFixed(1)       //=> "12345.7"   
      n.toFixed(5)       //=> "12345.67890"
      
      n.toExponential()  //=> "1.23456789e+4"
      n.toExponential(1) //=> "1.2e+4"
      
      n.toPrecision()    //=> "12345.6789"
      n.toPrecision(7)   //=> "12345.68"

      上述这些方法只能基于十进制数进行转换,且不能出现非法的尾随字符。下面介绍两个函数:

      parseInt()只解析整数,如果字符串前缀为“0x”或“0X”解析为十六进制数。可接受第二个参数为转换基数。

      parseFloat()可解析整数和浮点数。

      他们都会跳过任意数量的前导空格,并忽略数字字符后面的内容,且不进行四舍五入

      parseInt("123.8")               //=> 123: 去掉小数位
      parseInt("0xff")                //=> 255: 解析十六进制
      parseInt("    345.789 meters")  //=> 345: 忽略前导空格和数字之后的内容
      parseInt(".1")                  //=> NaN: 不能以非数字开头
      parseInt("11.6",2)              //=> 3: 二进制整数
      
      parseFloat("$123.6")            //=> NaN: 不能以非数字开头
      parseFloat(".1345 meters")      //=> 0.1345
3.8.3 对象转换为原始值
  • toString()

    返回一个反映这个对象的字符串。

    [1,2,3].toString()            //=> "1,2,3"
    new Date(2010,0,1).toString() //=> "Fri Jan 01 2010 00:00:00 GMT+0800 (CST)"
  • valueOf()

    如果存在任意原始值,它就默认将对象转换为表示它的原始值。

    var d=new Date(2010,0,1) //=> 2010年1月1日
    d.valueOf()              //=> 1262275200000

    日期对象与运算符的运行结果:

var dateNow= new Date();
typeof(dateNow + 1)           //=> "string" : "+"将日期转换为字符串
typeof(dateNow - 1)           //=> "number" : "-"使用对象到数字的转换
dateNow == dateNow.toString() //=> true: 隐式的和显式的字符串转换
dateNow > (dateNow - 1)       //=> true: ">"将日期转换为数字

3.9 变量声明

使用var声明变量,在存入值之前,初始值是undefined。

ECMAScript 5严格模式中,给一个没有声明的变量赋值也会报错。非严格模式下,会给全局对象创建一个同名属性。

3.10 变量作用域

一个变量的作用域(scope)是源代码中定义这个变量的区域。

全局变量拥有全局作用域;在函数内声明的变量以及函数参数都是局部变量。局部变量优先级高于同名的全局变量。

var scope = "global";
function checkscope(){
    var scope = "local";
    return scope;
}
checkscope() //=> "local"
3.10.1 函数作用域和声明提前

Javascript中没有块级作用域(block scope),取而代之的是函数作用域(function scope)。

Javascript特性(非正式名称)声明提前(hoisting),函数里声明的所有变量都被“提前”至函数体的顶部。

var scope = "global";
function fn(){
    console.log(scope)   //=> undefined
    var scope = "local";
    console.log(scope);  //=> local
}

等价于:

var scope = "global";
function fn(){
    var scope;
    console.log(scope)   //=> undefined
    scope = "local";
    console.log(scope);  //=> local
}
3.10.2 作为属性的变量

全局变量实际是全局对象的一个属性。当使用var声明变量时,这个属性不可配置,即无法通过delete删除。

var truevar = 1;      //声明一个不可删除的全局变量
fakevar = 2;          //创建全局对象的一个可删除的属性
this.fakevar = 3;
delete truevar       //=> false: 变量并没有被删除
delete fakevar       //=> true: 变量被删除
delete this.fakevar  //=>true: 变量被删除
3.10.3 作用域链

每段Javascript代码都有一个与之关联的作用域链(scope chain)。这个作用域链是一个对象列表或者链表,这组对象定义了这段代码“作用域中”的变量。

需要查找某个变量时(这个过程叫做“变量解析”),会从链中的第一个对象开始查找,如果没有会继续查找链上的下一个对象。 如果不存在,则抛出引用错误(ReferenceError)异常。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值