JS基础
立即执行函数
闭包
- 一个函数可以访问其他函数作用域内的数据
- 防抖
- 闭包内存泄漏
JS 诞生于1995年,它的出现主要是用来处理网页中的验证。由网景公司发明,起初命名为Livescript,后台由Sun公司介入更名javascript. 为了确保不同浏览器运行的javascript,几个公司共同定制js标准 ECMAScript.
alert('hello') // 控制浏览器弹出警告框
document.write() // 在页面中输出一个内容
console.log('hello') // 向控制台输出一个内容
-
js中严格区分大小写
-
字面量都是一些不可改变的值,可以直接使用,但一般不会直接使用字面量
-
变量可以保存字面量,且变量的值是可以被改变的,变量更加方便我们使用,很少直接使用字面量
-
标识符: 变量名,函数名,属性名
- 标识符可含有字母,数字,_, $
- 不能以数字开头、
- 不能是es中的关键字或保留字
- 一般使用驼峰命名法
- js底层保存标识符时实际用的是unicode编码
- 数据类型:
- 基本数据类型:string, number, boolean, null, undefined, 值和值之间没有任何的联系
- 引用数据类型:object, 可以保存多个不同数据类型的属性
- Number.MAX_VALUE
- js中可以表示的数字最大值 Number.MAX_VALUE, 值为1.7976931348623157e+308
- 如果数字超过最大值,会返回一个Infinity,表示正无穷, -Infinity表示负无穷
- typeof检查Infinity会返回number
- Number.MIN_VALUE
- 大于0的最小值 5e-324
- NaN
- NaN是一个特殊的数字,表示not a number
- 使用typeof检查一个NaN也会返回number
image.png
-
在js中整数的运算基本可以保证精确, 如果用js进行浮点运算,可能得到一个不精确的结果,所以千万不要用js进行对精确度要求较高的运算。
-
Null
- null 类型的值只有一个,就是null
- null这个值用来表示一个为空的对象
- 使用typeof检查返回object
- undefined
- undefined类型的值只有一个,就是undefined
- 当声明一个变量,但并不给变量赋值时,值为undefined
- 使用typeof检查返回undefined
image.png
- 强制类型转换
-
指将一个数据类型转换为其他的数据类型
-
类型转换主要指将其他数据类型转换为string, number, boolean
-
将其他的数据类型转换为string
toString()- 用被转换数据类型的toString()方法, 该方法不会影响到原变量,会将转换的结果返回
- null, undefined没有toString()方法
调用String函数
- 该方法不会影响到原变量,会将转换的结果返回,
- null, undefined也可以使用String函数.
- 使用String()函数做强制类型转换时,对于number和boolean实际上就是调用toString()方法
- 但是对于null和undefined,就不会调用toString()方法。会将null和undefined直接转换成‘null’, 'undefined'
-
将其他类型转换为Number
调用Number函数- 如果是纯数字的字符串,则直接转换成数字
- 如果字符串中有非数字的内容,则转成NaN
- 如果字符串是一个空串, 则转成0
- true转成1, false转成0
- null转为0, undefined转成NaN
parseInt() parseFloat() - parseInt() 可以将一个字符串中有效整数内容取出来
- parseFloat() 可以获得有效的小数
- 对非string类型使用,会先将其转换成string, 然后再操作
-
将其他类型转换成boolean
调用Boolean()函数- 数字 -> boolean: 除了0和NaN, 其余的都是true
- 字符串 -> boolean: 除了空串,其余都是true
- null和undefined -> boolean: 都是false
- 对象-> boolean: 也是true
- 进制
- 在js中,如果需要表示16进制的数字,需要以0x开头
- 如果需要表示8进制的数字,需要以0开头
- 如果需要表示2进制,则需要以0b开头
- 但不是所有浏览器都支持。'070' 这种字符串,有些浏览器会当成8进制解析,有些会当成10进制解析。
-
可以在parseInt() 传递一个第二个参数,表示数字的进制
image.png
- 运算符: 可以对一个或多个值进行运算,并获取运算结果
-
typeof就是运算符,可以获得一个值的类型,会将值的类型以字符串的形式返回 , string, boolean, undefined, object
-
算数运算符 + - * / %, 当对非number类型的值进行运算时 会先转成number类型再运算。任何值和NaN运算都为NaN。
-
‘’+‘’
如果对两个字符串进行加法运算, 则会做拼串。任何值和字符串相加都得字符串 -
任何值做 - * / 运算都会自动转换成number , 可以通过一个值-0 *1 /1来将其转换成number
-
一元运算符 + -
对于非number类型,会先转成number 然后在取正数/负数, 原理和Number()一样
image.png
-
逻辑运算符 || && !
! 非: 可以用来对一个布尔值取反,如果对非布尔值取反,会先将其转换为布尔值,然后再取反。可以对一个任意数据类型取两次反,来将其转换为布尔值。原理和Boolean()一样。
&& 与:只要有一个false, 就返回false
1)如果两值都为true,则返回后边的。
2)如果两值中有false,则返回靠前的false
|| 或:只要有一个true, 就返回true
1)如果两值都为true,则返回前边的。
2)如果两值中有true,则返回靠前的true
对于非boolean值与或操作时,会先将其转成布尔值, 再运算,并且返回原值。 -
赋值运算符 = +=(a=a+5 -> a+=5)
-
关系运算符 > < >= <=
对于非数字比较时,会先将其转成数字,再比较, 任何值和NaN做比较,都返回false
如果两边都是字符串做比较, 不会将其转换成数字比较,而是转成unicode做比较, 一位一位编码进行比较。如果两位一样,则比较下一位。
相等运算符 ==(会先做类型转换)===(不会做类型转换)
image.png
条件运算符 ?:
image.png
- Unicode
- 在字符串中使用转义字符输入unicode编码 \u四位编码
- 在网页中使用unicode编码 &#编码; (编码需要10进制)
- break和continue
- break: 可以用来退出switch和循环语句,不能在if语句中使用break和continue,会立即终止离他最近的那个循环语句。
可以为循环语句创建一个label,来标识当前的循环
label: 循环语句
使用break语句时,可以在break后跟着一个label,这样break会结束指定的循环,而不是最近的。
outer:
for (var i = 0; i < 5; i++) {
console.log('外层循环' + i);
for (var j = 0; j < 5; j++) {
break outer;
console.log('内层循环' + j);
}
}
image.png
- continue: 跳过当次循环
console.time('计时器名字') 可以开启一个计时器
console.timeEnd('计时器名字') 可以停止一个计时器
- 对象
- 内建对象
- 由ES标准中定义的对象,在任何的es的实现中都可以使用
- 比如Math, String, Number, Boolean, Function, Object
- 宿主对象
- 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
- 比如BOM, DOM
- 自定义对象
- 由开发人员自己创建的对象
- 添加属性 对象.属性名=属性值
- 删除属性 delete 对象.属性名
- 对象的属性名不强制要求遵守标识符的规范, 如果要使用特殊的属性名,不能使用.的方式来操作。 需要使用 对象['属性名']= 属性值
- in 运算符: 可以通过该运算符检查一个对象中是否含有指定的属性,如果有则返回true, 没有则返回false. '属性名' in 对象
- 基本数据类型和引用数据类型
- js 中的变量都是保存在栈内存中的
基本数据类型的值直接在栈内存中存储。
值与值之间是独立存在,修改一个变量不会影响其他的变量。
image.png
- 对象是保存到堆内存中的
每创建一个新的对象,就会在堆内存中开辟出一个新的空间,而变量保存的是对象的内存地址(对象的引用), 当一个通过一个变量修改属性时,另一个也会受到影响。
image.png
image.png
当比较两个基本数据类型的值时,就是比较值。
而比较两个引用数据类型时,比较的对象的内存地址。
如果两个对象一模一样,但地址不同,也会返回false
- 对象字面量
var obj = {};
使用对象字面量,可以在创建对象时,直接指定对象中的属性
var obj = {name:'name1', age: 22}
- 函数
函数也是一个对象。封装一些功能,在需要的时候调用。
-
创建一个函数对象,可以将要封装的代码以字符串的形式传递给函数
var fun = new Function("console.log('hello')"); fun(); -
函数声明 创建一个对象
function 函数名(形参1, 形参2)function fun2(){ cosole.log('hello'); } fun2(); -
使用表达式来创建一个函数
var 函数名=function([形参1, 形参2, ..., 形参n]) {}var fun3 = function() { console.log('匿名函数'); }; fun3();
函数也可以称为对象的属性,如果一个函数作为一个对象的属性保存,那么我们称这个函数是这个对象的方法,调用函数就是调用对象的方法。
-
立即执行函数: 函数执行完, 立即被调用,只执行一次
(function(){ alert('匿名函数'); })(); -
枚举对象中的属性
使用for…in语句
for(var 变量 in 对象){}var obj = { name: 'test', age: 10 } for (var i in obj) { console.log(i + ':' + obj[i]); } -
作用域
- 全局作用域:
- 在页面打开时创建,页面关闭时销毁
- 有一个全局对象window,代表的是浏览器的窗口,由浏览器创建,可直接使用
- 创建的全局变量都会作为window对象的属性保存
- 创建的函数都会作为window对象的方法保存
- 变量的声明提前: 使用var声明的变量,会在所有代码执行之前被声明(但不会赋值),但如果声明变量时不用var,则变量不会被声明提前。
函数的声明提前:使用函数声明形式创建的函数 function 函数(){} 会在所有代码执行之前就被创建。使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用。
- 函数作用域
- 调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁, 每次调用一次函数就会创建一个新的函数作用域,他们之间是相互独立的。在函数作用域中可以访问全局作用域的变量。
- 在函数作用域也有声明提前的特性。使用var关键字声明的变量,会在函数中所有的代码执行之前被声明。
- this
- 解析器在调用函数每次都会向函数内部传递一个隐含的参数,这个隐含的参数就是this. this 指向的就是一个对象,这个对象我们称为函数执行的上下文对象。
- 根据函数的调用方式的不同,this会指向不同的对象。
-
以函数的形式调用时, this永远都是window
-
以方法的形式调用时,this就是调用方法的那个对象。
-
构造函数
- 构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。
- 构造函数和普通函数的区别就是调用方式的不同,普通函数是直接调用, 构造函数需要使用new关键字调用。
- 构造函数的执行流程:
- 立刻创建一个新的对象
- 将新建的对象设置为函数中的this
- 逐行执行函数的代码
- 将新建的对象作为返回值返回
this的情况
- 以函数的形式调用,this是window
- 以方法的形式调用,谁调用方法,this就是谁
- 以构造函数形式调用,this就是新创建的那个对象
- 使用call,apply调用时,this是指定的那个对象
- 原型对象
- 我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype,这个属性对应着一个对象,这个对象就是我们所谓的原型对象。
- 如果函数作为普通函数调用prototype没有任何作用。
- 当函数以构造函数的形式调用时,它所创建的对象中都有一个隐含的属性,指向该构造函数的原型对象,我们可以通过proto来访问该属性。
- 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,可以将对象中共有的内容,统一设置到原型对象中。
- 当访问对象的一个属性或方法时,会先在对象自身中寻找,如果有,则直接使用,如果没有,则会去原型对象中寻找,如果找到,则直接使用。
- 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不用影响到全局作用域,就可以使每个对象都具有这些属性和方法了。
- 使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true.
- 可以使用对象的hasOwnProperty()来检查对象自身中是否含有该属性。
- 原型对象也是对象,也有原型
image.png
- toString()
- 当我们直接在页面中打印一个对象时,事实上是输出对象的toString()方法的返回值。
- 如果我们希望在输出对象时不输出【Object, Object】,可以为对象添加一个toString()方法。
28.垃圾回收
- 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须清理。
- 在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作,我们需要做的只是将不再使用的对象设置为null即可。
- 数组
- 数组也是一个对象,和普通对象功能类似,用来存储一些值
- 不同的是普通对象是使用字符串作为属性名的,而数组是使用数字来作为索引操作元素
- 索引: 从0开始的整数就是索引。
- 数组的存储性能比普通对象好,在开发中我们经常使用数组来存储一些数据。
- 向数组中添加元素 数组[索引]= 值
- 读取数组中的元素 数组[索引] 如果读取不存在的索引,返回undefined
- 获取数组的长度 数组.length
- 对于连续的数组, 使用length可以获得数组的长度
- 对于不连续的数组,使用length可以获得数组的最大索引+1
- 修改length:如果修改的length大于原长度,则多出部分会空出来,如果修改的length小于原长度,则对出的元素会被删除。
- 向数组的最后一个位置添加元素 数组[数组.length] = 值
- 使用字面量来创建数组: var arr = []; 使用字面量创建数组时,可以在创建时就指定数组中的元素
- 使用构造函数创建数组时,也可以同时添加元素,将要添加的元素作为构造函数的参数传递。
- 数组方法
- push(): 向数组的末尾添加一个或多个元素,并返回数组的新的长度
- pop(): 该方法可以删除数组的最后一个元素,并将被删除的元素作为返回值返回
- unshift(): 向数组开头添加一个或多个元素,并返回新的数组长度
- shift(): 可以删除数组的第一个元素,并将被删除的元素作为返回值返回
- forEach(): 只支持IE8以上的浏览器。需要一个函数作为参数,像这种函数,由我们创建但不由我们调用,称为回调函数。浏览器会在回调函数传递三个参数, 分别为当前正在遍历的元素,当前正在遍历的索引,正在遍历的数组。
- slice(): 从数组中提取指定元素。参数: 截取开始的位置的索引(包含开始索引), 截取结束的位置的索引(不包含结束索引,第二个参数可以不写,此时会截取从开始索引往后的所有元素)索引也可以传递一个负值,则从后往前计算,-1代表倒数第一个, 该方法不会改变元素数组,而是将截取到的元素封装到一个新数组中返回。
- splice(): 删除数组中的指定元素,使用splice()会影响到原数组,会将指定元素从原数组中删除。参数: 第一个表示开始位置的索引,第二个参数表示删除的数量, 第三个参数及以后可以传递一些新的元素,这些元素将会自动插入到开始位置索引前边。
去重:
image.png
- concat(): 可以连接两个或多个数组,并将新的数组返回,该方法不会对原数组产生影响。
- join(): 该方法可以将数组转换成一个字符串,该方法不会对原数组产生影响,而是将转换后的字符串作为结果返回。在join()中可以制定一个字符串作为参数,这个字符串将会成为数组中元素的连接符。
- reverse(): 该方法用来反转数组,会直接修改原数组。
-
sort(): 可以用来对数组进行排序,会影响原数组,默认会按unicode编码升序排序,所以对于数字进行排序时,可能会得到错误的结果。可以自己来指定排序的规则,在sort()添加一个回调函数,来指定排序规则。回调函数中需要定义两个形参,浏览器将会分别使用数组的元素作为实参去调用回调函数,使用哪个元素调用不确定,但肯定是在数组中a一定在b前边。浏览器会根据回调函数的返回值来决定元素的顺序,如果返回一个大于0的值,会交换顺序,如果小于等于0,不交换
image.png
- call(), apply()
- 这两个方法都是函数对象的方法,需要通过函数对象来调用
- 当对函数调用这两个方法都会调用函数执行
- 在调用这两个方法时,可以将一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this
- call() 方法可以将实参在对象后依次传递
-
apply() 方法需要将实参封装到一个数组中统一传递
image.png
- arguments
- 在调用函数时,浏览器每次都会传递两个隐含的参数:
-
函数的上下文对象 this
-
封装实参的对象 arguments
- arguments是一个类数组对象,可以通过索引来操作数据,可以获取长度
- 在调用函数时,传递的实参都会在arguments中保存
- arguments.length可以用来获取实参的长度,即使不定义形参,也可以通过arguments来使用实参
- 还有一个属性叫callee, 这个属性对应一个函数对象,就是当前正在指向的函数的对象
-
Date
-
Math
- Math 和其他对象不同,它不是一个构造函数,它属于一个工具类,不用创建对象,它里面封装了数学运算相关的属性和方法。
Math.PI - 圆周率
abs() - 计算一个数的绝对值
ceil() - 可以对一个数进行向上取整
floor() - 可以对一个数向下取整
round() - 四舍五入取整
random() - 用来生成[0, 1)之间的随机数, 生成一个x-y之间的数 Math.round(Math.random()*(y-x)+x)
max() - 获取多个数中最大值
min() - 获取多个数中最小值
pow(x,y) - x的y次幂
- 包装类
在js中,有3个包装类,通过这三个包装类可以将基本数据类型的数据转换为对象
String() - 将字符串转换成String对象
Number() - 将数字转换成Number对象
Boolean() - 将boolean转换成Boolean对象
实际应用中不推荐使用
-
方法和属性只能添加给对象,不能添加给基本数据类型,当我们对一些基本数据类型的值去调用属性和方法时,浏览器会临时使用包装类将其转换为对象,然后再调用对象的属性和方法,调用完以后,再将其转换成基本数据类型
var s = 123; s= s.toString();
-
字符串相关方法
在底层字符串是以字符数组的形式保存的。
image.png
image.png
- 正则表达式
- 用于定义一些字符串的规则,检查一个字符串是否符合规则。获取将字符串中符合规则的内容提取出来。
var 变量 = new RegExp("正则表达式", “匹配模式”)
匹配模式: - i: 忽略大小写
- g: 全局匹配模式
使用typeof检查正则对象,会返回object
test() - 使用这个方法可以检查一个字符串是否符合正则表达式的规则,如果符合返回true, 否则,返回false.
var reg= new RegExp('a'); 检查一个字符串中是否含有a
reg.test('abcdasd') -> true
使用字面量创建正则表达式
var 变量 = /正则表达式/匹配模式
检查一个字符串中是否有a或b, 使用 | 表示或者的意思
reg = /a|b/
检查一个字符串中是否有字母 [ab] == a|b
reg = /[A-z]/
检查一个字符串中是否含有abc,adc,aec
reg = /a[bde]c/
[^] 除了
reg = /^[ab]/
reg.test('abc') --- true
- 字符串和正则相关的方法
- split() 可以将一个字符串拆分成一个数组,方法中可以传递一个正则表达式作为参数,这样方法将会根据正则表达式去拆分字符串。
- search() 可以搜索字符串中是否含有指定内容,若搜索到,则返回第一次出现的索引,否则,返回-1
- match() 可以根据正则表达式从一个字符串中符合条件的内容提取出来.默认情况下,只会找到第一个符合要求的内容,可以设置为全局匹配模式,这样就会匹配到所有的内容
-
replace() 将字符串指定内容替换成新的内容,默认只会替换一个
image.png
量词
- 通过量词可以设置一个内容出现的次数
- {n} 出现n次
- {m,n} 出现m-n次
- {m,} 出现m次以上
- 至少一个,相当于{1, }
- 0个或者多个,相当于{0, }
- ? 0个或1个,相当于{0,1}
- ^ 表示开头
- $ 表示结尾
- . 表示任意字符
- \w 任意字母、数字,下划线
- \W 除字母、数字,下划线
- \d 任意数字
- \D 除数字
- \s 空格
- \S 除空格
- \b 单词边界
- \B 除单词边界
- DOM
Document Object Model: 文档对象模型, JS中通过DOM对html文档进行操作。
文档: 整个的html网页文档
对象: 将网页中的每一个部分都转换成一个对象
模型: 使用模型表示对象之间的关系,方便获取对象
节点(Node): 网页中的每一个部分都是节点
- 文档节点: 整个html文档
- 元素节点: html标签
- 属性节点: 元素的属性
-
文本节点: 文本内容
image.png
window.onload: 整个页面加载之后再触发事件
-
childNodes 属性会获取包含文本节点在内的所有结点,根据DOM标签标签间空白也会当成文本节点。在IE8及以下的浏览器中,不会将空白文本当成子节点。
-
children属性可以获取当前元素的所有子元素
-
firstChild可以获取当前元素第一个子节点(包括空白文本节点)
-
firstElementChild获取当前元素的第一个子元素,不支持IE8以下
-
document.body 获取body引用
-
document.documentElement 获取html标签
-
document.all 获取页面所有元素, 等同于document.getElementsByTagName('*')
-
document.getElementsByClassName() 可以根据class属性获取一组元素节点对象,不支持IE8以下的浏览器
-
document.querySelector() 需要一个选择器的字符串作为参数,可以根据一个css选择器来查询一个元素节点对象, 使用该方法只会返回唯一的一个元素
获取元素当前显示的样式: 元素.currentStyle.样式名 (只支持IE6),其他浏览器可以使用getComputerdStyle(), window方法,可直接使用。需要两个参数,一个是样式元素,另一个是伪元素,一般传null
40.JSON - JavaScript object Notation
json是一个特殊格式的字符串,这个字符串可以被任意语言所识别,可以转换为任意语言中的对象。在开发中主要用来数据交互。json和js对象格式一样,只是json字符串中的属性名必须加双引号。
json分类: 对象,数组
json中允许的值:字符串,数值,布尔,null,对象,数组
将json字符串转换成js中的对象 JSON.parse();
将js对象转换成json字符串 JSON.stringfy();
JSON在IE7以下浏览器中不支持
eval(): 可以用来执行一段字符串形式的js代码,并将执行结果返回
如果使用eval()执行的字符串中含有{},它会将{}当成是代码块,如果不希望将其当成代码块解析,则需要在字符串前后各加一个()性能比较差,同时还要安全隐患
虽然功能强大,但不建议在开发中使用,
eval("alert("hello")")
image.png
image.png