3 语言基础

59 阅读3分钟

语法

  • 注释,//或/* */
  • 标识符(变量、函数、类)
    • 第一个字符要求字母、下划线或$
    • 区分大小写
    • 不能是保留字、关键字、true、false、null
  • 语句结尾封号建议写上
  • 严格模式:脚本或函数头添加"use strict";

关键字和保留字

具体可查其他教程

变量

本质:保存任意值的命名占位符,所以声明时不需要指定类型
声明
- varvar message

变量提升:会将函数声明提升到作用域顶部,注意只是声明,直接使用值为undefined
作用域:函数作用域,函数内任何地方定义了,就会在运行前进行变量提升,故而在函数任何地方都能访问到,如果是在全局中,则会成为window对象(global对象)属性

var globalVar = '全局变量'
console.log(window.globalVar);//全局变量

console.log(message);//error!
function testVar(){
    console.log(message);//undefined
    var message = '初始化';
    coonsole.log(message);//初始化
}
- letlet message

与var的区别:

  • 变量提升:有提升,但是提升到暂时性死区,变量在没有执行声明之前访问,会提示ReferenceError
  • 作用域:块级作用域,注意每次循环都是新的块级作用域
  • 不可重复声明,混用也不行
  • 全局声明中不会成为window对象的属性
  • for循环中的let声明
//每次循环都会有新的块级作用域,也就是说每次循环的都声明一个新的迭代变量
//此迭代变量由于块级作用域,不能在循环外部访问
for(let i =0; i < 5; i++){
    setTimeout(()=>console.log(i),0)
}//0,1,2,3,4
console.log(i)//error!

//而var由于函数级作用域,每次循环其实是一个变量,最后函数访问的都是一个变量,且外部也能访问
for(var i =0; i < 5; i++){
    setTimeout(()=>console.log(i),0)
}//5,5,5,5,5
console.log(i)//5
  • constconst message
  • 与let基本一致
  • 必须赋予初始值,且限制的是不变,对于对象,则是变量保存的地址不变,对象内部可改变
  • for循环中,注意在每次循环中也会重新声明变量,但是不能在循环中改变const的值
//每次循环都会有新的块级作用域,也就是说每次循环的都声明一个新的迭代变量
//不可在迭代中改变值
for(const key in {a:1,b:2}){
    console.log(key);
}//a, b

for(const i = 0; i < 5; i++){
    setTimeout(()=>console.log(i),0)
}//error!循环内部自增了

数据类型

6种简单类型、1种复杂类型,共七种

  • 操作符typeof: typeof varNmae
    • 返回值少了null(默认null就是未赋值对象),多了function(区分普通对象)
    let varNull = null;
    function varFunction(){};
    console.log(typeof varNull);//object
    console.log(typeof varFunction);//function
    
  • Undefined
    • 字面值:undefined(假值)
    • 当let、var声明变量但没有初始化的时候,默认赋值了undefined
    • 怪异:对于没有声明的变量,调用typeof也会返回undefined
  • Null
    • 字面值:null(假值)
    • typeof null返回object,默认null表示空对象指针
    • undefined由null派生而来,console.log(null==undefined);//true
  • Boolean
    • 字面值:ture/false

    • 不等同于其他语言,true不等于1,false不等于0,但是0,1可转换成Boolean类型

    • if等控制语句会自动执行其他类型到Boolean类型的转换

    • Boolean()转型函数

      数据类型转换为true转换为false
      UndefinedN/Aundefined
      Number非00、NaN
      String非空字符串""
      Object任意对象,包括{}null
  • Number
    • 字面值:浮点数、整数、NaN(假值)、Infinity(真值)、-Infinity(真值)
    • js不显示区分整型和浮点型,但是由于浮点型占据整型空间两倍,js会尽可能将值用整型存储
    console.log(10.0 == 10)//true
    
    • 取值范围:[Number.MIN_VALUE,Number.MAX_VALUE],超过了就变为Infinity
    • NaN:表示不是数值,本来要返回数值的操作失败了(注意不会抛出错误),如0除0
    console.log(+0/-0)//NaN
    console.log(1/-0)//-Infinity
    
    • 数值转换Number()

      • Undefined、Boolean、Null类型,按照真假值映射到0,1
      • Number类型返回自身
      • String:
        • 空字符返回0
        • 字符串前后空格忽略,中间是正规数值(可由多个0开头)表示,则返回中间的数值
        • 否则返回NaN
      • 对象:
        • 调用valueOf(),按照上述规则转换,如果是NaN
        • 则调用toString()重新转换,即是最后结果
      console.log(Number('  00012.42'))//12.42
      console.log(Number(' +12.62 '))//12.62
      console.log(Number('j23'))//NaN
      
    • parseInt()
      • 从第一个非空格字符开始,若该字符不是+-或数值,立即返回NaN
      • 往后检测,直到字符串末尾或非数值字符
    • parseFloat()
      • 字符多了一个小数点
  • String
    • 字面量:"",'',``包裹普通字符或转义字符\
    • string是不可变的,当涉及改变时,都是在后台销毁原始字符串,然后将另一字符保存到该变量中,字符串变成值是为了在比较字符串的时候更加高效
      let stringVar = 'hello';
      stringVar = stringVar + 'world';//helloworld,原始的hello喝world都被销毁了
      
    • 模板字面量``
      • 其实更像js的表达式,取值后得到字符串
      • 会保留内部的换行符号、空格
      • 字符串插值${},里面可以是任意表达式
      //字符串之间直接就是进行值比较,相比于其他语言更方便
      let name="li"
      let age=19;
      console.log((name+' '+age)===`${name} ${age}`);//true
      
    • 标签函数:普通函数,只是调用方式不一样,用于对模板字面量自定义操作
    function tagFunction(strings,...template){
        //string是模板中以${}进行分割形成的列表
        //template是对每个${}中每个表达式求值后形成的列表
        return strings[0] + '<' + template[0] + '>';
    }
    let temp = 'juejing'
    //注意下面调用方式
    console.log(tagFunction`hello ${temp}`)//hello <juejing>
    
    • 原始字符串:\n直接显示,而不是换行,使用String.raw标签函数,注意调用方式
  • Symbol
    • 字面量:Symbel('描述'),如Symbol(key1)
    • 符号值是唯一的,用于确保对象属性唯一标识符
    • 创建方式:
      let symbolVar1 = Symbol('foo');
      let symbolVar2 = Symbol('foo');
      //Symbol()里面的值只是用来描述的,可以什么都不传
      console.log(symbolVar1 === symbolVar2);//false
      let symbolGlobal1 = Symbol.for('key1');
      let symbolGlobal2 = Symbol.for('key1');
      //Symbol.for()会用里面的值检测全局注册表,如果不存在,则注册后返回符号实例,存在则直接取出
      console.log(symbolGlobal1 === symbolGlobal2);//true
      console.log(symbolGlobal1);//Symbol(key1)
      console.log(Symbol.keyFor(symbolGlobal1))//key1
      
  • Object
    • 字面量:{key:value}
    • 创建:new constructor()
    • 实例属性及方法:
      • constructor:创建当前对象的函数
      • hasOwnProperty(propertyName):判断当前实例是否存在给定属性(String、Symbol)
      • isPrototypeOf(object):判断当前对象是否是object的原型
      • propertyIsEnumerable(propertyName):当前属性是否可枚举
      • toLocaleString():返回对象的字符串表示
      • toString():返回对象的字符串表示
      • valueOf():返回对象对应的字符串、数值或布尔值表示,通常与toString相同

操作符

  • 一元操作符:++,--,+,-:当用于非Number时,执行数值转换后再使用,+varName等价于Number(varName)
  • 位操作符:~,&,|,^,<<,>>(有符号),>>>(无符号)
  • 布尔操作符:
    • !,同样会执行类型转换,!!varName等价于Boolean(varName)
    • &&:并不会返回Boolean类型,存在短路,如果第一个为假值,则返回第一个值,不会执行第二个表达式,否则返回第二个表达式求值后的值
    • ||:与&&类似,只是短路在第一个表达式为真值时
  • 乘性操作符:*,/,也会类型转换
  • 指数:**,函数Math.pow()
  • 加性:+,注意的是如果两个都是number,则数值加,其他则转换成字符串
  • 减性:-,类型转换
  • 关系比较符:
    • <,>,<=,>=:存在类型转换
      • 有数值则按照数值比较,如果没有则执行字符串逐个字符比较
    • ==,!=:
      • 也有类型转换,依然数值优先
      • 若两个都是对象,则看是不是同一个对象
      • null喝undefined相等,除外与其他都不相等
      • NaN与任何值不相等,包括自身
    • ===,!==:不存在转换
  • 条件运算符:?:
  • 赋值与逗号:=,,应用场景:一条语句中声明多个变量let num1=1,num2=2;

语句

  • if,while,do-while,for
  • for-in:迭代对象中的非符号键属性,无序
  • for-of:遍历迭代元素,如数组集合
  • continue-break-标签语句 - continue/break lableName, 其中标签由特定语法声明lableName:statement
    let num=0;
    outerMost:
    for(let i = 0;i<10;i++){
        for(let j=0;j<10;j++){
            if(i == 5&&j==5){
                break outerMost
            }
            num++;
        }
    }
    console.log(num);//55
    
  • with(不推荐)
  • switch-case
    • switch()中的值不一定是数值,可以字符串或Boolean,只要case 后面的值与之全等即可

函数

  • return不跟值或不写return,不写则默认返回undefine
console.log((()=>{})())//undefined