JavaScript学习笔记
廖雪峰的 JavaScript 教程笔记
一些背景知识
只有JavaScript能跨平台、跨浏览器驱动网页,与用户交互
Node.js把JavaScript引入到了服务器端
JavaScript(对ECMAScript标准的一种实现)又称ECMAScript(一种语言标准)、ES6(ECMAScript 6)、ES2015(ECMAScript 2015)
Babel 是 JavaScript 转译器(也称源代码编译器),将使用了 ECMAScript 语言特性的 JavaScript 转换为只使用广泛支持的 ES5(ECMAScript 2009) 特性的等价代码。如Node.js使用的是 CommonJS 模块的 require 语法,之前不支持 import(不支持原生的ES6模块),则要用 babel 转译 js 模块为 CommonJS 模块
Webpack、Browserify 等打包工具主要是将 ES6 代码转译为 ES5 的 js 文件生成传统的代码包
数据类型
1、原始数据类型:数、字符串、布尔值、Symbol(ES6)、null、undefined
2、派生数据类型:对象(如:函数、数组、正则表达式)
变量
JavaScript严格区分大小写
JavaScript不区分整数和浮点数,统一用Number表示
== 和 === 的区别:== 会自动转换数据类型再比较,有时会得到奇怪的结果;=== 不会自动转换数据类型,若数据类型不一致,返回false,若一致,再比较。(JavaScript的设计缺陷,一般使用 === )
在 == 比较中,遇到比较的一方有数,则全部自动 toNumber(x) 转为数后比较,其中 toNumber(包含字母字符串) -> NaN,toNumber(undefined) -> NaN,toNumber(null) -> +0;
若比较的一方中有布尔值,则布尔值先被 toNumber(x) 转为数;
若比较的一方中有对象,则对象会被 toPrimitive(x) 转为字符串或数
在 === 比较中,类型相同则正常比较(除 NaN 外),类型不同则为 false,不同对象比较也为 false
//判断是否为NaN
NaN === NaN; // false
isNaN(NaN); // true(唯一判断NaN的方法)
null == undefined; //true
//浮点数比较
1 / 3 === (1 - 2 / 3); // false(因为计算机无法精确表示无限循环小数,浮点数运算时会产生误差)
Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true(只能计算浮点数之差的绝对值是否小于某阈值来比较两浮点数是否相等)
null 和 undefined:null 为空值,undefined 为未定义,一般用 null,undefined 仅在判断函数参数是否传递的情况下有用
JavaScript的一个数组中可以包含多种类型
JavaScript是变量本身类型不固定的动态语言,而静态语言(强类型语言)在定义变量时必须指定变量类型,如Java
变量是否用 var 声明:通过 var 声明的变量作用域为该变量被申明的函数体内。如果一个变量没有通过 var 申明就被使用,则该变量自动被申明为全局变量,这导致不同js文件中未通过 var 声明的同名变量间会相互影响(JavaScript设计缺陷)————解决:在代码第一行写上 'use strict';
启用strict模式,在strict模式下运行的JavaScript代码,强制通过 var 声明变量,使用未通过 var 声明的变量会报错
let 和 var:在同一作用域内重复声明变量,let会报错,var不会报错
const:const声明的变量是只读变量,若对 const 声明的变量重新用 let 或 var 声明会报错。且对于非对象类型(如数、布尔值、字符串)不可改变其值,但对于 const 声明的对象可改变其属性值,但不可对对象整体重新赋值(即变量本身的引用(内存中的引用地址)不可改)。
字符串
引号:字符串中包含单引号、双引号前面加转义符 \
,多行字符串用用 \n
表示(较早)或用反引号 `` (ES6)
模板字符串:用反引号括起来,其中用 ${变量名}
来表示相应值(ES6)
索引:字符串可以像数组一样通过索引取值,但不可通过索引赋值
部分方法:(调用时不改变原字符串,而是返回一新字符串)
toUpperCase() //变大写,str.toUpperCase()
toLowerCase() //变小写,str.toLowerCase()
indexOf() //搜索指定字符串出现的位置,空格也占一位置,str.indexOf('xxx');
substring(开始索引,结束索引) 或 substring(开始索引) //返回指定索引区间的子串,左闭右开,str.substring(0, 5);
数组
长度:数组.length
,给 length 属性赋值会改变原数组大小,并且若通过数组索引赋值时索引超出原大小也会改变数组大小
部分方法:
indexOf() //搜索指定的元素的位置,arr.indexOf(xxx)
slice() 或 slice(开始索引,结束索引) //返回指定索引区间元素,左闭右开,返回一个新数组,若无参则包含所有元素(可用于复制数组)
push(元素1,元素2,...) //在末尾添加元素,可加多个
pop() //返回并删除末尾元素,空数组 pop 不报错,返回 undefined
unshift(元素1,元素2,...) //在头部添加元素,可加多个
shift() //返回并删除头部元素
sort() //排序,直接改变原数组,arr.sort()
reverse() //倒序,直接改变原数组,arr.reverse()
splice(删除和添加的开始索引, 删除个数, 添加元素1, 添加元素2, ...) //删除和添加元素
concat() //连接数组,返回新数组,arr1.concat(arr2)
join(用于连接的字符) //数组连成字符串
展开运算符:在ES5中可用 apply()
把数组转为参数,ES6中可直接用 ...数组名
JavaScript 中数组是可修改对象,若添加元素,它就会动态增长
JavaScript 只支持一维数组,不支持矩阵,可通过数组嵌套数组来实现矩阵
类
ES5创建
function 类名(变量1,...,变量n){
this.属性1=变量1
this.属性n=变量n
}
类名.prototype.方法名 = function(){xxxxx}
ES6创建
class 类名{
constructor(变量1,...,变量n){
this.属性1=变量1
this.属性n=变量n
}
方法名(){xxxxx}
}
继承
class 子类名 extends 父类 {
constructor(变量1,...,变量n){
super(变量1,...,变量n-1) //调用父类构造函数
this.属性n=变量n
}
方法名(){xxxxx}
}
js 的面向对象编程还是基于原型实现的,ES6的类是基于原型语法的语法糖
对象
对象是类的实例
特殊属性名声明时用 ''
括起来,访问它时不用 对象.属性
,而用 对象['属性']
访问不存在的属性返回 undefined
删除属性 delete 对象.属性
或 ``
真假值
null、undefined、false、+0、-0、NaN、空字符串、不存在的对象属性为假,其余正常变量(如:1、-1)或对象(如:new String(‘’)、new Boolean(false))为真
函数
箭头函数可省略关键字 function,若函数体只有一行还可省略 {} 和 return(ES6)
函数的参数可设置默认值(ES6)
函数中有一个内置对象 arguments
(数组),包含函数被调用时传入的参数
可用展开运算符代替 arguments 来表示剩余参数,如 function a(x,y,...剩余参数整体的名字)
ES6 新特性
1、用 let 和 const 声明变量替代 var,作用域行为
2、模板字面量
3、解构:(1)一次初始化多个变量 let {x,y}={'a','b'}
(2)互换值 [x,y]=[y,x]
(3)属性简写(给属性同名变量赋值后即可表示对象)
4、展开运算符:(1)数组展开(2)表示剩余函数参数
5、箭头函数
6、函数可设置参数默认值
7、类
8、模块:使用 export {函数1,变量1,函数n}
导出,import {函数1,变量1,函数n} from 文件
导入
性能
1、相比于放在
标签里或使用 include 语句,在关闭 标签前引入 js 代码使得浏览器在加载脚本前解析和显示 HTML,有利于提升页面性能2、在类中声明函数时,可使用 prototype 方法来节约内存和降低实例化的开销。因为在类中声明函数时若通过 类.prototype.方法 = function () {xxxxx}
则函数只会被创建一次并在所有实例中共享;而通过在类定义里声明函数,则每个实例都会创建一个函数副本
TypeScript
TypeScript 是开源的、渐进式包含类型的 JavaScript 超集,它为 JavaScript 变量提供类型支持,TypeScript 会被编译为简单的 JavaScript 代码。虽然 TypeScript 在编译时会进行类型和错误检查,但错误不会阻止编译器生成 JavaScript 代码
定义变量
let a: tring = 'x'
let a: number = 10
let a: boolean
接口
第一种:自定义一种数据类型
第二种:与面向对象编程相关
interface 接口 {
函数1(参数): 类型
}
class 类 implements 接口 {
变量: 类型
函数1(参数): 类型{xxx}
}
泛型:指定函数的参数类型
interface 接口 <参数类型> {
函数1(参数): 类型
}
class 类 implements 接口 {
变量: 类型
函数1(参数:参数类型): 类型{xxx}
}