第3章 基本概念


# 第3章 基本概念

# 3.1 语法

# 3.1.1 标识符、注释

所谓标识符,就是指变量、函数、属性的名字,或者函数的参数,采用驼峰格式,第一个字母小写,剩下的每个单词的首字母大写,例如:

firstSecond
myCar
doSomethingImportant

ECMASCript使用C风格的注释,包括单行注释和块级注释

// 单行注释

/*
* 多行注释
*/

# 3.2 关键字和保留字

关键字是具有特定用途的,比如控制语句或其他特定操作,关键字、保留字、truefalsenull不能用作标识符:

关键字 关键字 关键字 关键字
break do instanceof typeof
case else new var
catch finally return void
continue for switch whitle
debugger function this with
default if throw
delete in try

保留字是将来可能有特定用途,但现在还没规定特定用途的。ES3定义的全部保留字:

保留字 保留字 保留字 保留字
abstract enum int short
boolean export interfact static
byte extends long super
char final native synchronized
class float package throws
debugger implements protected volatile
double import public let

# 3.3 变量

变量:可变的量,在编程语言中,变量其实就是一个名字,用来存储和代表不同值的东西。

用var操作符定义的碧昂量将成为定义该变量的作用域中的局部变量,如果在函数中使用var定义一个变量,那么这个变量在函数执行后就会被销毁。

声明变量有以下几种方式:

// ES3
var a = 123;
// ES6
let b = 100;
b = 200 //报错
const c = 1000;

// 创建函数也相当于在创建变量
function fn() {}

// 创建类也相当于创建变量
class A{}

// ES6的模块岛屿也可以创建变量
import a from './a.js'

// Symbol创建唯一值
let n = Symbol(100)
let m = Symbol(100)

总结:

  • var声明的变量,可以重复声明,后声明的会覆盖前面的
  • let声明的变量具有作用域,在同一作用域下不可重复声明变量,但是可以修改变量的值,例如let a = 1;,不能再次声明alet a = 2;会报错,提示:Uncaught SyntaxError: Identifier 'a' has already been declared
  • const声明的变量为常量,不能修改该变量的值,但是像Object这样的复杂数据类型,在内存中存放的是一个指向该对象的指针,也就是说,用const声明的对象仍然可以修改该对象的值,但不可再次声明该对象

# 3.4 数据类型

ESMAScript中数据分为两大类:一是基本数据类型:UndefinedNullBooleanNumberStringSymbol,二是复杂数据类型:Object,Object本质上是由一组无序的名子对组成的。

  • 基本数据类型

    • 数字Number (常规数字和 NaN)

    • 字符串 String

    • 布尔值 Boolean

    • 空指针 Null

    • 未定义 Undefined

    • 唯一值(独一无二的值)Symbol

  • 引用数据类型 Object对象类型

    • {} 普通对象
    • [] 数组对象
    • RegExp 正则对象
    • Function 函数数据类型
    • Math 数学函数对象
    • Date 日期对象

数据类型应用场景:

当我们通过Ajax请求拿到数据之前,先在本地初始化数据,一般都会先给一个默认的数据,请求数据后再把数据放入到我们定义好的数据结构里面,比如:

var data = {

    count: 0,
    isActive: true,
    goods: [],
    model: null,
    message: ''
  
}

# 3.4.1 typeof操作符

typeof操作符用于检测给定变量的数据类型。typeof操作符可以检测的数据类型有:

  • undefined
  • boolean
  • string
  • number
  • object
  • function
var message = 'some string'
console.log(typeof(message) // "string"

var arr = [1,2,3,4]
console.log(typeof(arr) // "object"
console.log(typeof(null) // "object"

在上面的例子中调用 typeof null会返回"object",因为特殊值null被认为是一个空的对象引用。用typeof检测一个变量是否是数组并不准确,会返回"object",使用Object.prototype.toString()检测数据类型更加准确

# 3.4.2 Undefined类型和Null类型

undefined类型只有一个值,即特殊的undefined,一个变量声明了但未赋值,默认是undefined

var message;
console.log(message == undefined) // true

undefinednull区别:

nullundefined都代表的是没有。 null是意料之中:一般都是开始不知道值,我们手动先设置为null,后期再给予赋值操作,例如,let num = null,一般最好用null作为初始的空值,因为0值不是空值,它在栈内存中有自己的存储空间(占了位置) undefined是意料之外:不是我们能决定的,创建一个变量没有赋值,默认是undefined

let num = null;
null = 12;

# 3.4.3 Boolean类型

只有两个字面值;true和false,这两个值与数字值不是一回事,因此true不一定等于1,而false也不一定等于0。

只有0NaN''nullundefined五个值转换为false,其余都转换为true(而且没有任何的特殊情况)

数据类型 转换为true的值 转换为false的值
Boolean true false
String 任何非空字符串 ""空字符串
Number 任何非零数字值(包括无穷大) 0 和 NaN
Object 任何对象 null
Undefined 不适用 undefined
Boolean(true) // true
Boolean(false) // false
Boolean('Hello Wolrd') // true
Boolean() // false
Boolean('') // false
Boolean(' ') // true (里面有空格)
Boolean(1) // true
Boolean(0) // false
Boolean(NaN) // false
Boolean({}) // true
Boolean([]) // true
Boolean(null) // false
Boolean(undefined) // false

把其他类型转换为布尔类型有三种方式:

  1. Boolean()
  2. !!! 取反:先转为布尔,然后取反
  3. 条件判断

# 3.4.4 Number类型

Number类型使用IEEE754格式来表示整数和浮点值,这也是0.2 + 0.3不等于0.5的原因,

最基本的数值类型字面量格式是十进制整数

var a = 10;

# 1. 浮点数值

整理中。。。

# 2. NaN

Not a Number:不是一个数,但它属于数值类型

NaN的特点

  • NaN和任何值进行操作都会返回NaN
  • NaN与任何值都不相等,包括NaN本身
console.log(NaN == NaN)

# 3. isNaN函数

用于检测一个变量不是数值(Number)类型。isNaN()接收一个参数,这个参数可以是任何类型。这个函数会尝试把传入的参数转换为数值,某些不是数值的值会直接转换成数值,例如字符串"10"Boolean值,不能转换为数值的值返回true,能转换的返回false

console.log( isNaN(NaN ) // true 
console.log( isNaN(10 ) // false
console.log( isNaN('10') // false
console.log( isNaN('blue') // true
console.log(isNaN( true )) // false (true会被转换成1)

总结:

  • isNaN意思是:是不是非数值,是的话返回true,所有能被该函数转换能Number类型的值,都返回false
  • 在使用isNaN进行检测的时候,首先会验证检测的值是否为数字类型,如果不是,先基于Number()这个方法,把值转换成数字类型,然后再检测。
  • 空字符串、空数组、布尔值、null会转成数值,所以isNaN函数返回false
  • 空对象、函数、undefined不能转换成数值,返回true

# 4. 数值转换

把非数值值转换为数值:

  • Number()
  • parseInt() 取整
  • parseFloat() 浮点数

`Number()转换规则

  • 如果是布尔值,truefalse会被转换为10
Number(true) // 1
Number(false) // 0
  • 如果是数字,只是简单的传入和返回。
Number(1) // 1
Number(100) // 100
  • 如果是null值,返回0
Number(null) // 0

  • 如果是undefined,返回NaN
Number(undefined) // NaN

  • 如果是字符串:
    • 字符串中只包含数字(包括前面带正/负号的情况),则将其转换为十进制数值,数字前面有0的会被忽略(不管前面有几个0,全部忽略),例如"010"会转换成10
    • 字符串中包含有效的浮点格式,如"1.1",则将其转换为对应的浮点数值。
    • 字符串中包含有效的十六进制格式(一般用数字09和字母AF(或a~f)表示,其中:A~F表示10~15,这些称作十六进制数字),如"0xf",将其转换成相同大小的十进制整数值。
    • 字符串为空,转换成0
    • 字符串中包含除了以上格式之外的字符,则转换为NaN,如字符串中既有数字又有字母的情况。

// 规则一
Number("1") // 1
Number("123") // 123
Number("010") // 10 (前导的0会被忽略)
Number("-10") // -10

// 规则2
Number("1.1") // 1.1
Number("0.1") // 0.1
Number("0000.1") // 0.1 (前导的0会被忽略)

// 规则3
Number(0xf) // 15

// 规则4
Number("") // 0
Number(" ") // 0
Number('') // 0

// 规则5
Number("Hello Wolrd") // NaN
Number("0ff6600") // NaN
Number("ff6600") // NaN
Number("0.1a") // NaN
Number("10a") // NaN
Number("a10.1") // NaN

var goodsList = {
    'pop':
}

var arr = [1,2,3,4]
Number(arr)
  • 如果数组或对象,返回NaN(估计没有人会这么傻,用Number()函数去转换吧...)。

# parseInt(string,radix)

将一个字符串转换成x进制的整数。

传入的第一个参数为字符串,如果参数不是字符串,则将其转换为字符串(使用 ToString 抽象操作)。字符串开头的空白符将会被忽略。

第二个参数为整数,表示按照xx进制转换,如传入参数10表示按十进制规则转换,

从左到右依次查找有效数字字符,直到遇到非有效数字字符,停止查找(不管后面是否好友数字),把找到的当做数字返回。

如果字符串中以0x开头且后跟数字字符,就会将其当做一个十六进制整数。

如果字符串以"0"开头且后跟数字字符,则会被当做一个八进制数来解析。

如果不传第二个参数,会按照八进制解析。在大多数情况下,我们要解析的都是十进制数值,因此始终将10作为第二个参数是非常必要的。

parseInt("123abc") // 123
parseInt("") // NaN
parseInt("12.5px") // 12
parseInt("0xA") // 10 (16进制)
parseInt("0xf") // 15 (16进制)
parseInt("070") // 70
parseInt("70") // 70

# parseFloat(string)

解析一个参数(必要时先转换为字符串)并返回一个浮点数。默认解析十进制值。

function circumference(r) {
  return parseFloat(r) * 2.0 * Math.PI;
}

console.log(circumference(4.567));
// expected output: 28.695307297889173

console.log(circumference('4.567abcdefgh'));
// expected output: 28.695307297889173

  • 从左到右依次解析字符,一直解析到字符串末尾,遇到非数字字符会或遇到第二个浮点数(在这之前的字符串都会被解析)会使解析停止,如"3.14"解析成3.14"3.14.1234"解析成3.14

  • 忽略参数首尾空白符


parseFloat("3.14") // 3.14
parseFloat("-3.14") //-3.14
parseFloat("+3.14") //3.14
parseFloat("0003.14") // 3.14
parseFloat(" 3.14 ") // 3.14
parseFloat("3.14abc") // 3.14
parseFloat("3.14.5678") // 3.14
parseFloat("abc3.14") // NaN
parseFloat("abc123") // NaN
parseFloat("123abc") // 123


总结:

为什么NumberparseInt/parseFloat计算结果不一样呢?

  • Number转换规则是浏览器底层渲染规则,是浏览器的一个非常重要的方法,parseInt/parseFloat是一个单独方法的规则,就是用来处理字符串的。

  • Number走的是整个V8引擎最底层的机制,遇到其他类型,底层机制会告诉我们哪个类型跟哪个类型应该怎么转换,这是底层机制已经规定好的,比如遇到布尔值,true转为1false转为0 parseIntparseFloat是额外提供的方法,就是浏览器提供的方法,它们的源码处理机制很简单,会先把传入的参数转换为字符串,然后在从左到右查找数字有效字符。


let a = 12;

a>=0&& a<=20?(a%2===0?a+=2:null):a-=2 //a => 14

let a = 12;
if(a>=2&&a<=20) {
    if(a%2 === 0) {
        a+=2;
    }
} else {
    a-=2;
}
console.log(a)

# 3.4.5 String类型

所有用单引号、双引号、反引号包起来的都是字符串。

# 把其他类型值转换为字符串

  • [val].toString()
  • 字符串拼接
var age =18;
var ageAsString = age.toString() // "11"

let a = 10 + null + true + [] + undefined + 'Hello' + null + [] + 10 + false;

console.log(a) // 11undefinedHellonull10false
console.log(let a = 10 + null + true + [] + undefined + 'Hello' + null + [] + 10 + false;

console.log(10 + null + true + [] + undefined + 'Hello' + null + [] + 10 + false)

let str = 'Hello World'

案例解析:

  • 第一步,10 + null => 10 null转换成数值为0, 10 + 0 = 10。
  • 第二步,10 + true => 11 true转为为数值为1,10 + 1 = 11
  • 第三步, 11 + [] => "11" []转换为字符串为空,数值和遇到字符串+号变为连接符11 + "" = "11"
  • 第四步, "11" + undefined => "11undefined" 字符串后使用+号,当做连接符,后面的也一样
  • 所有最终结果为 11undefinedHellonull10false

# 3.4.6 Object类型

ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过执行new操作符狗跟需要创建的对象类型名称来创建。对象实例拥有属性property和方法method

// 声明方式1
var obj = new Object()
// 声明方式2
var obj = {}

每个Object实例都拥有下列属性和方法:

  • constructor:保存用于创建当前对象的函数。
  • hasOwnProperty(propertyName):用于检查给定属性在当前对象实例中是否存在。
  • isPortotypeOf(object):传入对象是否是另一个对象的原型。
  • propertyIsEnumberable(propertyName):用于检查给定的属性是否能够使用for-in语句来枚举。
  • toLocaleString():返回对象的字符串表示。该字符串与执行环境的地区对应。
  • toString():返回对象的字符串表示。
  • valueOf():返回对象的字符串、数值或者布尔值表示。通常与toString()方法的返回值相同。

# 3.5 操作符

# 3.5.1一元操作符

# 1. 递增和递减操作符

# 2. 一元加和减操作符

# 3.5.2 位操作符

# 3.5.3 布尔操作符

# 1.逻辑非 !

# 2. 逻辑与 &&

逻辑与操作,有两个操作数(条件)

var result = true && false;
第一个操作数 第二个操作数 结果
true true true
true false false
fasle true false
false false false

# 3.

# 3.6 语句

# 3.7 函数

# 3.8 小结

JavaScript的核心语言特性在ECMA-262中以名为ECMAScript的伪语言的形式来定义的。ECMAScript中包含了所有基本的语法、操作符、数据类型以及完成基本的计算任务说必须的对象,但没有对取得输入和产生输出的机制做出规定。理解ECMAScript以及其复杂的各种细节,是理解其在Web浏览器中的实现——JavaScript的关键。下面总结了ECMAScript中基本的要素。

  • ECMAScript中的基恩数据类型包括Undefined、Null、String、Number、Boolean和Symbol。
  • 与其他语言不通,ECMAScript没有整数和浮点数值分别定义不通的数据类型,Number类型可以用于表示所有数值。
  • ECMaScript中也有一种复杂的数据类型,即Object类型,该类型是这门语言中所有对象的基础类型。
  • 严格模式为这门语言中容易出错的地方施加了限制。 ECMAScript提供了很多与C及其他类C语言中相同的基本操作符,包括算数操作符、布尔操作符、关系操作符、相等操作符及赋值操作符等。
  • ECMAScript从其他语言中借鉴了很多流程控制语句,例如if语句、for语句和switch语句等。
  • 无须指定函数的返回值,因为任何ECMAScript函数都可以在任何时候返回值,实际上,未指定返回值的函数返回的是一个特殊的undefined值。
  • ECMAScript中也没有函数签名的概念,因为其函数参数是以一个包含零或多个值的数组的形式传递的。
  • 可以向ECMAScript函数传递任意数量的参数,并且可以通过arguments对此昂来访问这些参数。
  • 由于不存在函数签名的特性,ECMAScript函数不能重载。
上次更新: 10/26/2019, 11:44:13 PM