js知识点梳理-js概述

189 阅读10分钟

概念: JavaScript 是运行在js解释器的【解释性】【弱类型】【面向对象】的脚本语言

  • js解释器:①嵌入浏览器内核,不需要安装;②独立安装的
  • 解释型:运行之前不需要检查语法是否正确,直接运行,碰到错误停止
    • 编译型:运行之前需要检查语法是否正确,若不正确则不能运行
  • 弱类型:由【数据】决定数据类型,变量可以保存任意数据类型
    • 强类型:由数据类型决定保存的数据是什么
  • 面向对象:万物皆对象,可以设置属性和方法

作用: 补充css功能;Ajax和服务器能进行交互

注释: //

输出

  1. 控制台输出 console.log()
  2. 页面输出 document.write()
  3. 弹出框输出 alert()

变量&常量

  1. 变量:var 变量名=值
    • 作用:经常使用的数据可以提前保存起来,且数据可随时修改
    • 注意:
      • 变量名:不以数字开头,不能使用关键字,尽量见名知意
      • 创建变量时可不赋值,默认undefined
      • 创建变量时可不使用var关键字,直接定义变量 --【全局污染】
      • 创建多个变量时,可以用一个关键字var,变量间用“,”连接
  2. 常量:const 常量名=值
    • 注意:一旦创建,值不可修改

数据类型

  1. 原始/基本/值类型:
    • Number 数字,取值:无数个
    • String 字符串,取值:无数个
    • Boolean 布尔值,取值:true/false
    • Undefined 变量的默认值,取值:undefined
    • Null 空,用完的变量可以使用null释放
  2. 引用/对象类型

包装类型: 将原始类型的值变为一个引用类型的对象

  • 为什么:前辈们发现字符串/数字/布尔经常都会被拿来使用,所以提前提供了包装类型封装为一个引用类型的对象,提供我们一些属性和方法(便于程序员操作)
  • 何时使用:只要在你试图用原始类型的值去调用属性或者方法时,会自动套上包装类型
  • 何时释放:属性或方法调用完毕后,包装类型自动释放
  • 为什么undefined和null不能使用.:不具有包装类型,没有任何的属性和方法

数据类型的转换

Number、String、Boolean

1. 隐式转换

  • “+” 若碰到一个字符串,那么两边的数据都会转换为字符串,进行【拼接】操作
  • “-*/%” 字符串可以转为数字,但必须是纯数字的字符串,只要包含任一非数字字符,结果则为【NaN】
  • 常见转换:true->1 false->0 undefined->NaN "100"->100 "100px"->NaN
  • NaN:Not A Number,不是一个数字,但是是Number类型
    • 缺点:NaN参与任何算术运算,结果仍为NaN
    • NaN参与任何比较/关系运算,结果都为false
    • 解决 !isNaN(x);//判断是不是有效数字(true->有效数字)(false->NaN)

2. 显式/强制转换

  • 转字符串
    • xx.toString();//undefined和null不支持
    • String(x);
  • 转数字
    • parseInt(str/num) 从左到右依次读取每个字符,碰到非数字字符则停止,并且不认识小数点,若一来就不认识则为NaN
    • parseFloat(str)从左到右依次读取每个字符,碰到非数字字符则停止,认识第一个小数点,若一来就不认识则为NaN
    • Number()相当于隐式转换
  • 转布尔 Boolean();
    • 只有6个转换结果为false:0,"",undefined,null,NaN,false

运算符

算术运算符

分类:+-*/%

算术运算具有隐式数据类型转换,默认会转为数字。

比较/关系运算符

分类:> < >= <= == != === !==

结果:true、false

比较运算符常用于分支、循环的判断条件之中,比较运算符也具有隐式转换

注意:

  • 若参与比较的两个都是字符串,按位比较每个字符的十六进制Unicode号或十进制ASCII码
    • 0-9<A-Z<a-z
    • 汉字的第一个字:一 4e00(ASCII:19968)
    • 汉字的最后一个字:yu 9fa5(ASCII:40869)
  • NaN 参与任何比较运算,结果都为false
    • !isNaN(x)
    • x是一个数字->true;x是NaN->false
  • undefined===null
    • === 数据类型和数值都相同,结果为false
    • ===和!== 无隐式转换

逻辑运算符

分类:&& || !

  1. && 与

全部条件都为true,结果为true;任一条件为false,结果为false

  1. || 或

全部条件为false,结果为false;任一条件为true,结果为true

  1. ! 非

!true -> false
!false -> true

  1. 短路逻辑 只要前一个条件已经可以得出结论,则后续条件不执行
  • && 若前一个条件满足,则后一个操作执行;若前一个条件不满足,则后一个操作不执行
    • 用于简化if(){} 条件&&(操作)
  • || 两个值中二选一,用于兼容

位运算符

  1. 左移

m<<n 读作:m左移了n位,实际是m*2的n次方

  1. 右移

m>>n 读作:m右移了n位,实际是m/2的n次方

赋值运算

分类:+=,-=,*=,/=,%=,++,--

  • 递增vs累加
    • 递增:i++ 一次只能+1
    • 累加:i+=n 自定义,每次加n
  • i++ vs ++i
    • 单独使用时,i++和++i没有区别
    • 参与别的表达式时,变量的值会+1,但:++i返回的是+1之后的新值,i++返回的是+1之前的旧值

三目运算

用于简化if...else / if...else if...else

条件?操作1:默认操作

条件1?操作1:条件2?操作2:条件3?操作3:默认操作

注意:

  • 只能完成简单分支:操作只有一句话
  • 默认操作不能省略

程序的结构

顺序结构

默认,从上向下依次执行每一句代码

分支结构

根据判断条件,选择一部分代码

if

  1. 一个条件一件事:满足就做,不满足就不做
    if(判断条件){
        操作;
    }
  1. 一个条件两件事:满足就做第一件,不满足就做第二件
    if(判断条件){
        操作1;
    }else if{
        默认操作;
    }
  1. 多个条件多件事:满足哪个就做哪个
    if(条件1){
        操作1;
    }else if(条件2){
        操作2;
    }else if(条件3){
        操作3;
    }else{
        默认操作;
    }

注意:

  • 最后的else可以省略,但条件都不满足的时候,分支无效
  • 条件有顺序,因为分支只走一条路

switch

    switch(变量/表达式){
        case1:
        操作1;
        break;
        case2:
        操作2;
        break;
        default:
        默认操作;
    }

注意:

  • 默认只要满足一条路,会把后面所有操作做完->break:通常放在操作后面
    • 最后的default默认操作,不用加break
    • 连续多个操作相同,可省略中间部分
  • 不具有隐式转换
  • default可省略
  • switch相对if效率更高,但不能实现范围判断

循环结构

根据判断条件,选择是否重复执行某一段代码

for

for(var 循环变量;循环条件;循环变量的变化){
    循环体;
}

循环变量处可以创建多个变量

while

    var 循环变量;
    while(循环条件){
        循环体;
        循环变量的变化;
    }

do...while

    var 循环变量=几;
        do{
        循环体;
        循环变量变化;
    }while(循环条件)

循环终止语句

  • break 退出整个循环
  • continue 退出本次循环

死循环

while(true){循环体}

for(;;){循环体} 执行原理:先判断循环条件,条件为真,执行一次;重复判断至条件为假,才会停止

注意:循环是一次一次执行的,不是同时执行

js的组成

ECMAScript 核心语法

DOM(Document Object Model)文档对象模型 --操作文档

BOM(Browser Object Model)浏览器对象模型 --操作浏览器

作用域

作用域分类

全局作用域: 全局变量和全局函数,在任何位置都可以访问/使用

函数/局部作用域: 局部变量和局部函数,只在当前函数调用时内部可用

作用域的使用规则

优先使用自己的,自己没有找全局,全局没有则报错

  • 注意:
    • 不要对未声明的变量直接赋值,会导致全局污染
    • 所有变量使用前都要先var,不要对没有var的变量直接赋值
  • 哪些属于局部变量?
    • 直接在函数作用域中创建的变量
    • 形参

声明提前

程序执行前,将var声明的变量和function声明的函数集中提前到当前作用域的顶部,但

  • 赋值留在原地
  • 变量比函数轻,变量在前

按值传递

两个变量之间进行赋值

  1. 传递原始类型的值:两个变量之间赋值,做操作时互不影响(深拷贝:复制副本)
  2. 传递引用类型的值【Array、Function】:两个变量之间赋值,做操作时相互影响(浅拷贝:传递地址值)

预定义的全局函数

编码和解码

前端将用户输入的网址的中文【编码】为单字节字符,后端再将前端传递内容【解码】为原文

  • 编码 var code=encodeURIComponent("str");
  • 解码 var 原文=decodeURIComponent(code);

isFinite(num);

判断num是否再有效范围内,三种情况为false:分母为0,NaN,Infinity

parseInt/parseFloat/isNaN

ES5

1.保护对象

对象的每一个属性都有4大特性

  • true 保存实际值
  • writable 开关:控制属性是否可以被修改 默认true
  • enumerable 开关:控制属性是否可以被for in循环 默认true
  • configurable 开关:控制属性是否可以被删除 默认true
    • 一旦被设置为false,则不允许修改其他特性,改为false则不可逆

修改对象的某个属性

Object.defineProperty(xx,"id",{特性})

Object.defineProperties(xx,{
    "id":{四大特性},
    "name":{四大特性},
    "salary":{四大特性}
});

保护对象的三个级别

  • 防扩展/防添加 Object.preventExtensions(obj)
  • 密封(防添加、防删除) Object.seal(obj)
  • 冻结(防添加、防删除、防修改) Object.freeze(obj)

2.数组的新API(简化for循环)

判断

every 每一个都满足(类似&&) 任一为false,则为false

some 任一满足(类似||) 任一为true,则为true

    arr.every/some(function(val,i,arr){
        return 判断条件
    })

注意:

  • 三个参数val i arr 并非都需要传入,看需要使用哪些
    • val 当前值
    • i 当前值下标
    • arr 数组本身
  • function中的return未写时,默认为undefined

遍历

forEach 直接修改原数组

arr.forEach(function(val,i,arr){
    arr[i]*=2;//arr[i]=val*2
})

map 不修改原数组,直接返回新数组

var newArr=arr.map(function(val,i,arr){
    return val*2;
})

汇总和过滤

过滤: 筛选出符和条件的元素(不修改原数组)

var subArr=arr.filter(function(val,i,arr){
    return 条件;
})

汇总

var subArr=arr.reduce(function(prev,val,i,arr){
    return prev*val;
},base)

3.根据一个父对象创建子对象

var 子对象=Object.create(父对象){
    "属性1":{四大特性},
    "属性2":{四大特性},
    "属性3":{四大特性}
}

4.call/apply/bind:替换了函数中的this

call/apply

临时替换了函数中的this,类似“借”。两者的区别为传参形式

call 实参单独传入方法名.call(借用对象,实参)

apply 传入实参整理为数组,传入数组参数方法名.apply(借用对象,[实参])

常用:

  1. Object.prototype.toString.call/apply(数组);
  2. Math.max/min.apply(Math,arr);
  3. 将类数组转为普通数组lis=Array.prototype.slice.call(this)
//摇号
var lis=document.getElementsByTagName("li");
var list=document.getElementsByTagName("ul")[0];

lis=Array.prototype.slice.call(lis);

var nums=[];

while(nums.length<lis.length){
    var r=parseInt(Math.random()*(lis.length)+1);
    if(nums.indexOf(r)==-1){
        nums.push(r)
    }
}

lis.forEach((val,i) => val.setAttribute("count",nums[i]));
lis.sort((a,b) => a.getAttribute("count")-b.getAttribute("count"));
lis.forEach(val => list.appendChild(val));

bind

永久替换了函数中的this,类似“买”【不会立即执行】

var 新函数名=方法名.bind(永久绑定的对象,永久绑定的参数,...);

  • 创建了一个功能和原函数完全相同的新函数
  • 将新函数的this永久绑定为指定对象
  • 将新函数中部分固定参数提前永久绑定

5.严格模式

开启严格模式use strict

  • 放在作用域顶部
  • 严格模式下禁止给未声明变量赋值
  • 将静默失败升级为错误

ES6

1.模板字符串

支持直接在字符串中书写变量我的名字叫${name}

2.块级作用域

将var替换为let,用于创建变量

  • let前不允许出现未声明的同名变量(解决声明提前)
  • 添加了块级作用域,{}相当于一个块
  • 绑定事件时记录当前元素下标,不需要自定义下标 for(let i=0;i<lis.length;i++){}

3.箭头函数:简化回调函数

去掉function,()和{}之间添加=>

  • 若形参只有一个,省略()
  • 若函数体只有一句话,省略{}
  • 若函数体只有一句return,return可以省略
  • 箭头函数中的this会指向外部的对象

4.for of循环

for(var v of arr){console.log(v)}

  • v:value,
  • 循环拿到每个值
  • 不能遍历hash,不能遍历对象
  • 不能直接修改原数组,返回新数组