JavaScript基础概念
标识符
- 指变量、函数、属性的名字,或者函数的参数
标识符的书写有几个特征
- 区分大小写
- 第一个字符必须是字母、下划线(_)、或者是$
- 后面的可以是字母、数字、下划线、$
命名规约
- 使用是实际意义的单词
- 变量使用驼峰规则,第一个单词首字母小写,后面单词首字母大写
- 变量使用名词,方法函数使用动词开头,常量全部用大写字母,函数创建对象首字母大写
|
|
变量
- JavaScript中变量是用来保存值的占位符,定义变量的时候要使用var运算符,后面跟一个作为名称的标识符即可
|
|
弱类型
- 在一些编译语言(C、Java、C#)等变量的类型是固定的,在声明变量的时候就要标识其类型,在程序执行前编译阶段变量的类型就确定了,而且不能改变,称之为强类型
|
|
- 解释型语言(PHP、JavaScript)等变量的类型是松散的,一个变量可以用来保存任何类型的数据,变量的类型不是由声明时决定(声明的时候只是用了var运算符),而是在程序执行阶段由其值的类型决定,随着程序运行其值类型改变,变量类型也会发生改变
|
|
语句
- 语句(statement)是为了完成某种任务而进行的操作,比如下面就是一行赋值语句
|
|
- 这条语句先用var运算符,声明了变量a,然后将 1+2 的运算结果赋值给变量a
- JavaScript中语句以;结束,一行可以包含多条语句,如果省略分号不会产生语法错误,解释器会自动判断语句结束
|
|
表达式
- 一个为了得到返回值的计算式(凡是JavaScript语言中预期为值的地方,都可以使用表达式)
|
|
- 语句和表达式的区别在于,前者主要为了进行某种操作,一般情况下不需要返回值;后者则是为了得到返回值,一定会返回一个值
表达式的几种形式
原始表达式
- 常量、变量、保留字
对象、数组初始化表达式
- var obj = {a:1,b:2};
- var a =[1,2,3];
函数定义表达式
- var fn = function(){}
属性访问表达式
- Math.abs
调用表达式
- alert(‘hello’)
对象创建表达式
- new object()
- 变量名也是表达式,因为计算出的结果就是赋值给变量的值
变量提升
- JavaScript引擎的工作方式是,先解析代码,获取所有被声明的变量,然后再一行一行地运行。这造成的结果,就是所有的变量的声明语句,都会被提升到代码的头部,这就叫做变量提升
|
|
- 实际上执行过程是解释器在未执行的时候先解析出变量声明,然后给他初始值undefined,然后才逐句执行程序
|
|
注释
- 通过注释功能让js引擎忽略部分语句,用来解释我们的部分语句
- 两种注释:一种是单行注释,用//起头;另一种是多行注释,放在/ 和 /之间
|
|
关键字和保留字
- 关键字是JavaScript引擎会用到的一些字,我们标识符不能再使用
- break\case\catch\continue\default\delete\do\else\finally\for\function\if\in\instanceof\new\return\switch\this\throw\try\typeof\var\void\while\with
- js还规定了一些不能用作标识符的保留字,这些字符没有什么意义,但是未来会用到
- abstract\boolean\byte\char\class\const\debugger\double\enum\export\extends\final\float\goto\implements\import\int\interface\long\native\package\private\protected\public\short\static\super\synchronized\throws\transient\volatile
JavaScript语法
CSS和JS放置顺序
- 浏览器渲染机制一种是等全部加载后再一起渲染(IE、Chrome),另一种是边加载边渲染(Firefox)
- 常用方法:根据不同浏览器渲染机制不同一般选用折中的方法来解决即CSS一般用style标签放在的末尾,而JS放置在末尾
|
|
- CSS放置在head,浏览器会先读取CSS的样式,当读到里面的内容时候,读一个添加一个样式;如果CSS放在后面,对于IE、Chorme浏览器,可能出现白屏问题;对于Firefox浏览器,可能会出现无样式内容闪烁
- JS放置在后面,JS加载的过程中,其它HTML、CSS等读取会停下来,等待JS加载完后在读取后面的内容,JS阻塞了后面内容的呈现以及后面组件的加载;故采取HTML和CSS先静态页面出来,再读取JS,让页面动起来
白屏和FOUC
白屏
- 网页无任何内容样式呈白色背景的现象
出现白屏的情况
- 对于IE、Chrome,CSS样式放在底部,页面出现白屏而不是内容逐步展现
- @import标签,即使CSS放入link,并且放在头部也会出现白屏(直接link放在顶部代替@import)
- 对于CSS加载可以并发加载,而加载JS是会禁用并发,所以JS放在顶部也会导致白屏
FOUC(无样式内容闪烁)
- 页面只有HTML结构无样式的现象
出现FOUC的情况
- 对于Firefox,CSS样式放在底部,浏览器逐步呈现无样式的内容,所以用户看到的页面就是无样式内容闪烁
- 白屏和FOUC出现的原因是因为两种浏览器的渲染机制不同造成的,所以解决办法就是将CSS放在顶部,这样不管浏览器渲染机制如何,最先得到CSS样式一般就不会出现这两种情况
async和defer的作用
- 默认情况下,读到script标签会立即加载并执行脚本,阻塞后面的内容
|
|
async
- js加上async后,这条js不会阻塞后面的内容,两者并行执行,并且这条js加载完成后会马上执行
|
|
defer
- js加上defer后,这条js不会阻塞后面的内容,两者并行执行,但这条js是被加载,执行要等到所有元素解析完成之后
|
|
区别
- async不保证js的执行顺序,谁先加载完就谁先执行
- defer保证了js的执行顺序,加载完了都不许执行,等所有元素解析完了,js再一条一条执行
网页的渲染机制
- 浏览器读取HTML,构建DOM树
- 浏览器读取CSS,构建CSSOM树
- 浏览器将DOM树和CSSOM树,组合成渲染树 (render tree)
- 在渲染树的基础上进行布局,计算每个节点的几何结构
- 浏览器把每个节点绘制到屏幕上
不同的浏览器,呈现机制不一样
IE和chrome
- 浏览器会把所有的HTML内容都添加上CSS样式后,再呈现出来,内容过多样式加载过慢会出现白屏问题
Firefox
- 浏览器会渲染一句呈现一句
- 如果CSS放在头部,就会页面一点一点呈现
- 如果CSS放在尾部,就会出现无样式内容闪烁
数据类型(5+1种)
- 数值(number):整数和小数(比如1和3.14)
- 字符串(string):字符组成的文本(比如”Hello World”)
- 布尔值(boolean):true(真)和false(假)两个特定值
- undefined:表示“未定义”或不存在,即此处目前没有任何值
- null:表示空缺,即此处应该有一个值,但目前为空
- 对象(object):各种值组成的集合
|
|
- 数值、字符串、布尔值称为原始类型的值,最小单元;对象称为复杂类型的值,是多个原始类型的集合
- undefined和null是两个特殊值
- 对象分狭义的对象(object)、数组(array)、函数(function)等等
Boolean
- 布尔值代表“真”和“假”两个状态。“真”用关键字true表示,“假”用关键字false表示。布尔值只有这两个值
下列运算符会返回布尔值
- 两元逻辑运算符: && (And),|| (Or)
- 前置逻辑运算符: ! (Not)
- 相等运算符:===,!==,==,!=
- 比较运算符:>,>=,<,<=
如果JavaScript预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是除了下面六个值被转为false,其他值都视为true
- undefined
- null
- false
- 0
- NaN
- “”(空字符串)
|
|
Number
- JavaScript的数字类型和其它语言有所不同,没有整型和浮点数的区别,统一都是Number类型,可以表示十进制、八进制、十六进制
|
|
浮点数
- 浮点数是指数字包含小数点,小数点后至少有一位数字(没有或者是0会转为整数),前面可以没有
|
|
- 对于极大或极小的数字可以使用科学计数法
|
|
- 浮点数最高精度是17位,但是在计算的时候精度不如整数
|
|
- Infinity:表示无穷大
|
|
String
- String是Unicode字符组成的序列,俗称字符串,可以用双引号或者单引号表示,没有区别,匹配即可
|
|
Object
- 对象,就是一种无序的数据集合,由若干个“键值对”(key-value)构成。key我们称为对象的属性,value可以是任何JavaScript类型,甚至可以是对象
|
|
对象属性的读取方式
|
|
- 对象的属性key不确定而是一个变量的时候必须使用[]
- []里可以是任何字符串,而.不能
- 使用.属性可以不加引号,使用[]属性当是常量的时候必须加引号
NaN、undefined、null
NaN
- NaN,即非数值(Not a Number)是一个特殊的数值,这个数值用于表示一个本来要返回数值的操作数未返回数值的情况(这样就不会报错了),即出现在将字符串解析成数字出错的场合
- NaN和任何值不相等,包括本身
- 任何涉及NaN的操作都会返回NaN
- NaN的数据类型是Number类型
- isNaN()函数,确定是否为NaN
|
|
undefined
- 表示不存在值,就是此处目前不存在任何值,典型用法如下
- 变量被声明了,但没有赋值时,就等于undefined。
- 调用函数时,应该提供的参数没有提供,该参数等于undefined。
- 对象没有赋值的属性,该属性的值为undefined。
- 函数没有返回值时,默认返回undefined
|
|
null
- 表示空指针,即该处的值现在为空对象,典型用法如下
- 作为函数的参数,表示该函数的参数是一个没有任何内容的对象
- 作为对象原型链的终点
|
|
typeof和instanceof
- JavaScript有三种方法,可以确定一个值到底是什么类型,如下
- typeof运算符
- instanceof运算符
- Object.prototype.toString方法
typeof
- typeof运算符可以返回一个值的数据类型
原始类型
- 数值、字符串、布尔值分别返回number、string、boolean
|
|
函数
- 函数返回function
|
|
undefined
- undefined返回undefined
- typeof可以用来检查一个没有声明的变量,而不报错
|
|
object
- 除此以外,其他情况都返回object
|
|
- 空数值[]返回值也是object,说明数组本质上也是一种特殊的对象
- 历史原因造成null返回object,null本质上是一种类似undefined的特殊值
instanceof
- instanceof 是判断变量是否为某个对象的实例,返回值为true或false
|
|
如何判断一个变量是否是数字、字符串、布尔、函数
- typeof 运算符可以判断一个变量是否是数字、字符串、布尔、函数
数字
|
|
字符串
|
|
布尔
|
|
函数
|
|
NaN
- NaN是JavaScript的特殊值,表示“非数字”(Not a Number),主要出现在将字符串解析成数字出错的场合
|
|
- 上面代码运行时,会自动将字符串x转为数值,但是由于x不是数值,所以最后得到结果为·NaN·,表示它是“非数字”(NaN)
- 一些数学函数的运算结果会出现NaN
|
|
- 这些计算在数学上本来就是错误的,所以计算结果返回NaN
判断NaN 的方法
- isNaN() ,判断一个数是否为NaN,返回 true 或false,但是只对数值有效,不是数值的参数会先转化成数值,当转化不了的时候就转成了NaN,所有这个方法判断不一定准确
- 判断NaN更可靠的方法是,利用NaN是JavaScript之中唯一不等于自身的值这个特点,进行判断
|
|
非数值转化为数值
- 有三个函数可以把非数值转化为数值
- Number () 把给定的值转换成数字
- parseInt () 把值转换成整数
- parseFloat () 把值转换成浮点数
Number ()
- 如果是Boolean值,true 返回 1,false 返回 0
|
|
- 如果是数字,就是原样
|
|
- 如果是null,返回 0
|
|
- 如果是undefined,返回NaN
|
|
- 如果是字符串,有以下规则
- 如果是字符串中只包含数字(包括前面带正号或负号的情况),则将其转化成十进制数值
|
|
- 如果字符串中包含的有效的浮点数,就会转化成对应的浮点数,前面的0会忽略
|
|
- 如果字符串中包含有效的十六进制格式,前面为0x的格式,会自动转化成相同大小的十进制数
|
|
- 如果字符串是空字符串,则返回 0
|
|
- 如果字符串中包含上述格式外的其他字符,则转化成NaN
|
|
parseInt ()
- parseInt方法用于将 字符串 转为整数。返回值只有两种可能,不是一个十进制整数,就是NaN
|
|
- 如果parseInt的参数不是字符串,则会先转为字符串再转换
|
|
- 字符串转为整数的时候,是一个个字符依次转换,如果遇到不能转为数字的字符,就不再进行下去,返回已经转好的部分
|
|
- 如果字符串的第一个字符不能转化为数字(后面跟着数字的正负号除外),返回NaN
|
|
- parseInt方法还可以接受第二个参数(2到36之间),表示被解析的值的进制,返回该值对应的十进制数。默认情况下,parseInt的第二个参数为10,即默认是十进制转十进制
|
|
parseFloat ()
- parseFloat用于将一个字符串转为浮点数
|
|
- 如果第一个字符不能转化成浮点数,就返回NaN
|
|
parseFloat () 和 Number () 的区别
- 一般Number()比较复杂,所以建议使用parseFloat ()
|
|
JS中=、==、===的区别
- JS中的=、==、===是不同的
“=”表示赋值
- 把后面的值赋给前面
|
|
“==”相等运算符
宽松的比较两个数据,如果两个数据类型相同,就直接比较,如果两个数据类型不同,则会先转化数据类型相同,再比较
- 原始类型间的比较
|
|
- 对象与原始类型比较
|
|
- undefined 和 null
|
|
“===” 严格相等运算符
严格相等运算符(===)比较它们是否为“同一个值”。如果两个值不是同一类型,严格相等运算符(===)直接返回false
- 不同类型的值
|
|
- 同一类的原始类型值
|
|
- 同一类的复合类型值
|
|
break和continue
break
- break用于强制退出本次循环
|
|
continue
- continue用于退出本次循环,执行下次循环
|
|
void 0 和 undefined在使用场景上有什么区别
- void 0 运算后返回值是 undefined,不可被重写
- undefined 在局部作用域中,是可以被重写的,如果要判断一个变量是否和 undefined 相等,可以使用 void 0 来进行比较
|
|
code:完成如下代码判断一个变量是否是数字、字符串、布尔、函数
|
|
explain
|
|
code:以下代码的输出结果是?
|
|
explain
|
|
- 运算符通常会对操作数进行类型的转换,称隐式类型转换
code: 以下代码的输出结果是?
|
|
explain
|
|
code: 以下代码的输出结果是?
|
|
explain
|
|
code:遍历数组,把数组里的打印数组每一项的平方
|
|
explain
|
|
code:遍历JSON,打印里面的值
|
|
explain
|
|
code:下面代码的输出是什么?
|
|
explain
|
|
- js存在变量提升机制,使得a声明提升至最前面,此时a没有赋值所以是undefined;到a=1时,给a赋值1,输出1;最后b未声明所以控制台报错
code:如下代码输出什么
|
|
explain
|
|
运算符
- 运算符是处理数据的基本方法,用来从现有数据得到新的数据
加法运算符
- 加法运算符(+)是最常见的运算符之一,但是使用规则却相对复杂。因为在JavaScript语言里面,这个运算符可以完成两种运算,既可以处理算术的加法,也可以用作字符串连接,它们都写成+
|
|
- 在两个操作数都是数字的时候,会做加法运算
- 两个参数都是字符串或在有一个参数是字符串的情况下会把另外一个参数转换为字符串做字符串拼接
- 在参数有对象的情况下会调用其valueOf或toString
- 在只有一个字符串参数的时候会尝试将其转换为数字
- 在只有一个数字参数的时候返回其正数值
|
|
算术运算符
- 加法运算符(Addition):x + y
- 减法运算符(Subtraction): x - y
- 乘法运算符(Multiplication): x * y
- 除法运算符(Division):x / y
- 余数运算符(Remainder):x % y
- 自增运算符(Increment):++x 或者 x++
- 自减运算符(Decrement):–x 或者 x–
- 数值运算符(Convert to number): +x
- 负数值运算符(Negate):-x
余数运算符
- 余数运算符(%)返回前一个运算子被后一个运算子除,所得的余数
|
|
自增和自减运算符
- 自增和自减运算符,是一元运算符,只需要一个运算子。它们的作用是将运算子首先转为数值,然后加上1或者减去1。它们会修改原始变量
|
|
- 自增和自减运算符有一个需要注意的地方,就是放在变量之后,会先返回变量操作前的值,再进行自增/自减操作;放在变量之前,会先进行自增/自减操作,再返回变量操作后的值
|
|
数值运算符
- 数值运算符(+)同样使用加号,但是加法运算符是二元运算符(需要两个操作数),它是一元运算符(只需要一个操作数)
- 数值运算符的作用在于可以将任何值转为数值(与Number函数的作用相同)
|
|
负数值运算符
- 负数值运算符(-),也同样具有将一个值转为数值的功能,只不过得到的值正负相反。连用两个负数值运算符,等同于数值运算符
|
|
赋值运算符
- 赋值运算符(Assignment Operators)用于给变量赋值。最常见的赋值运算符,当然就是等号(=),表达式x = y表示将y的值赋给x。除此之外,JavaScript还提供其他11个复合的赋值运算符
|
|
比较运算符
- == 相等
- === 严格相等
- != 不相等
- !== 严格不相等
- < 小于
- <= 小于或等于
大于
= 大于或等于
- 比较运算符用于比较两个值,然后返回一个布尔值,表示是否满足比较条件,JavaScript一共提供了8个比较运算符
|
|
布尔运算符
- 取反运算符:!
- 且运算符:&&
- 或运算符:||
- 三元运算符:?:
取反运算符(!)
- 取反运算符形式上是一个感叹号,用于将布尔值变为相反值,即true变成false,false变成true
- 不管什么类型的值,经过取反运算后,都变成了布尔值
- 对一个值连续做两次取反运算,等于将其转为对应的布尔值,与Boolean函数的作用相同。这是一种常用的类型转换的写法
|
|
且运算符(&&)
- 第一个操作数为true并且第二个操作数为true,返回true
- 且运算符的运算规则是:如果第一个运算子的布尔值为true,则返回第二个运算子的值(注意是值,不是布尔值);如果第一个运算子的布尔值为false,则直接返回第一个运算子的值,且不再对第二个运算子求值
|
|
- 这种跳过第二个运算子的机制,被称为“短路”。有些程序员喜欢用它取代if结构,比如下面是一段if结构的代码,就可以用且运算符改写
|
|
- 且运算符可以多个连用,这时返回第一个布尔值为false的表达式的值
|
|
或运算符(||)
- 只要一个操作数是true,则返回是true
- 或运算符(||)的运算规则是:如果第一个运算子的布尔值为true,则返回第一个运算子的值,且不再对第二个运算子求值;如果第一个运算子的布尔值为false,则返回第二个运算子的值。短路规则对这个运算符也适用
|
|
- 或运算符可以多个连用,这时返回第一个布尔值为true的表达式的值
|
|
- 或运算符常用于为一个变量设置默认值
|
|
三元条件运算符(?:)
- 三元条件运算符用问号(?)和冒号(:),分隔三个表达式。如果第一个表达式的布尔值为true,则返回第二个表达式的值,否则返回第三个表达式的值
|
|
- 通常来说,三元条件表达式与if…else语句具有同样表达效果,前者可以表达的,后者也能表达。但是两者具有一个重大差别,if…else是语句,没有返回值;三元条件表达式是表达式,具有返回值。所以,在需要返回值的场合,只能使用三元条件表达式,而不能使用if..else
|
|
位运算符
- 或运算(or):符号为|,表示若两个二进制位都为0,则结果为0,否则为1。
- 与运算(and):符号为&,表示若两个二进制位都为1,则结果为1,否则为0。
- 否运算(not):符号为~,表示对一个二进制位取反。
- 异或运算(xor):符号为^,表示若两个二进制位不相同,则结果为1,否则为0。
- 左移运算(left shift):符号为<<
- 右移运算(right shift):符号为>>
- 带符号位的右移运算(zero filled right shift):符号为>>>
- 这些位运算符直接处理每一个比特位(bit),所以是非常底层的运算,好处是速度极快,缺点是很不直观,许多场合不能使用它们,否则会使代码难以理解和查错
- 有一点需要特别注意,位运算符只对整数起作用,如果一个运算子不是整数,会自动转为整数后再执行。另外,虽然在JavaScript内部,数值都是以64位浮点数的形式储存,但是做位运算的时候,是以32位带符号的整数进行运算的,并且返回值也是一个32位带符号的整数
其他运算符
void运算符
- void运算符的作用是执行一个表达式,然后不返回任何值,或者说返回undefined
|
|
逗号运算符
- 逗号运算符用于对两个表达式求值,并返回后一个表达式的值
|
|
运算顺序
优先级
- JavaScript各种运算符的优先级别(Operator Precedence)是不一样的。优先级高的运算符先执行,优先级低的运算符后执行
|
|
- 上面的代码中,乘法运算符(*)的优先性高于加法运算符(+),所以先执行乘法,再执行加法,相当于下面这样
|
|
- 上面代码中,变量y的值就很难看出来,因为这个表达式涉及5个运算符,到底谁的优先级最高,实在不容易记住。
- 根据语言规格,这五个运算符的优先级从高到低依次为:小于等于(<=)、严格相等(===)、或(||)、三元(?:)、等号(=)。因此上面的表达式,实际的运算顺序如下
有几个我们需要注意的地方
- typeof的优先级相当的高,比加减乘除神马的都高,所以虽然是操作符,在复杂表达式的时候我们还是习惯加括号
|
|
- ++、–是右结合的操作符(优先级最高的几个都是右结合),而且比加减乘除优先级高。同时自增、自减运算符的运算数得是左值(可以放在赋值符号左边的值),而不能是常数
|
|
- 赋值运算符的优先级相当的低
|
|
- 逻辑非!也在优先级队列的前端,比加减乘除高,但逻辑与、逻辑或优先级很低,不如加减乘除
|
|
流程控制语句
条件语句
- 条件语句提供一种语法构造,只有满足某个条件,才会执行相应的语句
if语句
- if结构先判断一个表达式的布尔值,然后根据布尔值的真伪,执行不同的语句
- 如果condition为true,就执行紧跟在后面的语句;如果结果为false,则跳过不执行
|
|
- condition可以是任意表达式,结果不一定是布尔值,JavaScript解释器会自动调用Boolean()将表达式结果转为布尔值
- 注意,if后面的表达式,不要混淆“赋值表达式”(=)与“严格相等运算符”(===)或“相等运算符”(==)。因为,“赋值表达式”不具有比较作用
if…else结构
- if代码块后面,还可以跟一个else代码块,表示不满足条件时,所要执行的代码
|
|
- 对同一个变量进行多次判断时,多个if…else语句可以连写在一起
|
|
switch结构
- 多个if…else连在一起使用的时候,可以转为使用更方便的switch结构
|
|
- 假如没有break语句,导致不会跳出switch结构,而会一直执行下去
- switch语句在比较值的时候使用全等操作符,不会进行类型转换
|
|
- 这是另一种写法,之所以给表达式传递true,因为每个case值都可以返回一个布尔值
三元运算符 ?:
- JavaScript还有一个三元运算符(即该运算符需要三个运算子)?:,也可以用于逻辑判断
|
|
循环语句
- 循环语句用于重复执行某个操作,它有多种形式
while循环
- While语句包括一个循环条件和一段代码块,只要条件为真,就不断循环执行代码块
|
|
for循环
- for语句是循环命令的另一种形式,可以指定循环的起点、终点和终止条件
|
|
for语句后面的括号里面,有三个表达式
- 初始化表达式(initialize):确定循环的初始值,只在循环开始时执行一次。
- 测试表达式(test):检查循环条件,只要为真就进行后续操作。
- 递增表达式(increment):完成后续操作,然后返回上一步,再一次检查循环条件
do…while循环
- do…while循环与while循环类似,唯一的区别就是先运行一次循环体,然后判断循环条件
|
|
break语句和continue语句
- break语句和continue语句都具有跳转作用,可以让代码不按既有的顺序执行
break语句
- break语句用于跳出代码块或循环
|
|
continue语句
- continue语句用于立即终止本轮循环,返回循环结构的头部,开始下一轮循环
|
|
标签(label)
- JavaScript语言允许,语句的前面有标签(label),相当于定位符,用于跳转到程序的任意位置
- 标签可以是任意的标识符,但是不能是保留字,语句部分可以是任意语句
- 标签通常与break语句和continue语句配合使用,跳出特定的循环
|
|
- 不建议使用此语句,看起来很复杂的嵌套
JavaScript函数
- 函数就是一段可以反复调用的代码块。通过名字来供其它预计调用以执行函数包含的多条代码语句
|
|
函数声明和函数表达式的区别
函数声明
- function关键字声明一个函数
|
|
函数表达式
- 用var 声明一个变量,将函数(匿名函数)赋值给这个变量
|
|
- 还有一种是构造函数方式,用new来创建一个函数对象,很少用到,不推荐
|
|
区别
- 函数声明,声明会提前
- 函数表达式,函数声明不会提前
|
|
变量和函数的声明前置
- JS和C、java等语言不同,JS能够在变量的函数被声明之前使用它们
变量的声明前置
- 用var创建变量,声明会前置
|
|
- 一定要var声明的变量才会声明提升
|
|
函数的声明前置
- 用function声明函数,函数声明会前置
|
|
arguments
定义
- 由于JavaScript允许函数有不定数目的参数,所以我们需要一种机制,可以在函数体内部读取所有参数。这就是arguments对象的由来
用法
读取参数
- arguments对象包含了函数运行时的所有参数,arguments[0]就是第一个参数,arguments[1]就是第二个参数,以此类推。这个对象只有在函数体内部,才可以使用
|
|
参数赋值
- arguments对象除了可以读取参数,还可以为参数赋值(严格模式不允许这种用法)
|
|
查询参数个数
- 可以通过arguments对象的length属性,判断函数调用时到底带几个参数
|
|
与数组的关系
- arguments很像数组,但它是一个对象。数组专有的方法(比如slice和forEach),不能在arguments对象上直接使用
- 但是,可以通过apply方法,把arguments作为参数传进去,这样就可以让arguments使用数组方法了
|
|
- 要让arguments对象使用数组方法,真正的解决方法是将arguments转为真正的数组。下面是两种常用的转换方法:slice方法和逐一填入新数组
|
|
callee属性
- arguments对象带有一个callee属性,返回它所对应的原函数
|
|
- 可以通过arguments.callee,达到调用函数自身的目的。这个属性在严格模式里面是禁用的,因此不建议使用
函数的重载实现
- 指同一范围内声明几个同名函数,它们的功能类似,但是形参不同(指参数的个数、类型或者顺序不同)
|
|
- JavaScript 中,没有重载,同名函数会覆盖;但可以在函数体针对不同的参数调用执行相应的逻辑
|
|
立即执行函数表达式(IIFE)
- JavaScript中,声明一个函数,要想运行它,就要调用它,这是函数的使用方式;如果想要声明这个函数并且立即运行它,就可以把这个函数声明变成表达式,后面加上()就可以立即执行这个函数
|
|
- 立即执行函数的作用是:不必为函数命名,避免了污染全局变量;IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量
递归实现n!
- 自己调用自己
- 设定终止条件
|
|
code:以下代码输出什么
|
|
explain
|
|
code:写一个函数,返回参数的平方和
|
|
explain
|
|
code:如下代码的输出?为什么
|
|
explain
|
|
code:如下代码的输出?为什么
|
|
explain
|
|
code:如下代码输出什么? 写出作用域链查找过程伪代码
|
|
explain
|
|
code:如下代码输出什么? 写出作用域链查找过程伪代码
|
|
explain
|
|
code:以下代码输出什么? 写出作用域链的查找过程伪代码
|
|
explain
|
|
code:以下代码输出什么? 写出作用域链查找过程伪代码
|
|
explain
|
|
JavaScript引用类型、对象拷贝
引用类型和基本类型
引用类型
- 保存在堆内存中的对象,变量中保存的实际上只是一个指针,这个指针执行内存中的另一个位置,由该位置保存对象
- 对象、数组、函数、正则都是引用类型
基本类型
- 保存在栈内存中的简单数据段
- 数值、布尔值、null和undefined都是基本类型
code:如下代码输出什么?
|
|
explain
|
|
code:如下代码输出什么?
|
|
explain
|
|
code:如下代码输出什么?
|
|
explain
|
|
code:过滤如下数组,只保留正数,直接在原数组上操作
|
|
explain
|
|
code:过滤如下数组,只保留正数,原数组不变,生成新数组
|
|
explain
|
|
对象拷贝
code:对象深拷贝
explain
|
|
JavaScript字符串、JSON
字符串
code:使用数组拼接出如下字符串
|
|
explain
|
|
code:写出两种以上声明多行字符串的方法
explain
|
|
code:补全如下代码,让输出结果为字符串:hello\\小明
|
|
explain
|
|
code:以下代码输出什么?
explain
|
|
code:写一个函数,判断一个字符串是回文字符串
explain
|
|
code:写一个函数,统计字符串里出现频率最多的字符
explain
|
|
code:写一个camelize函数,把my-short-string形式的字符串转化成myShortString形式的字符串
explain
|
|
code:写一个ucFirst函数,返回第一个字母为大写的字符串
explain
|
|
code:写一个函数truncate(str,maxlength),如果str的长度大于maxlength,会把str截断到maxlength,并加上…
explain
|
|
JSON
JSON的简介
- JSON 是文本格式,能用于在不同编程语言中交换结构化数据
- 大部分编程语言中存储文本数据的数据类型,在这些编程语言中你可以把 JSON (文本)存储在字符串内
- JSON抄袭js的语法,但是它有严格的语法规范
JSON语法规则
- 复合类型的值只能是数组或对象,不能是函数、正则表达式对象、日期对象
- 简单类型的值只有四种:字符串、数值(必须以十进制表示)、布尔值和null(不能使用NaN, Infinity, -Infinity和undefined)
- 字符串必须使用双引号表示,不能使用单引号
- 对象的键名必须放在双引号里面
- 数组或对象最后一个成员的后面,不能加逗号
|
|
JSON对象
- ES5新增了JSON对象,用来处理JSON格式数据。它有两个方法:JSON.stringify()和JSON.parse()
JSON.stringify()
- JSON.stringify方法用于将一个值转为字符串。该字符串符合 JSON 格式,并且可以被JSON.parse方法还原
|
|
JSON.parse()
- JSON.parse方法用于将JSON字符串转化成对象
|
|
code:JSON和字符串互相转化
|
|
JavaScript的Math对象、数组操作、Date对象
Math对象
- Math是JavaScript的内置对象,提供一系列数学常数和数学方法
- 该对象不是构造函数,不能生成实例,所有的属性和方法都必须在Math对象上调用
code:写一个函数返回从min到max之间的随机整数,包括min不包括max
explain
|
|
|
|
code:写一个函数返回从min到max之间的随机整数,包括min包括max
explain
|
|
|
|
code:写一个函数,生成一个长度为n的随机字符串,字符串字符的取值范围包括0到9,a到z,A到Z
explain
|
|
code:写一个函数,生成一个随机IP地址,一个合法的IP地址为0.0.0.0~255.255.255.255
explain
|
|
code:写一个函数,生成一个随机颜色字符串,合法的颜色为#000000~#ffffff
explain
|
|
数组操作
数组方法
push()
- push方法用于在数组的末端添加一个或多个元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组
|
|
pop()
- pop方法用于删除数组的最后一个元素,并返回该元素。注意,该方法会改变原数组
|
|
- push和pop结合使用,就构成了“后进先出”的栈结构(stack)
shift()
- shift方法用于删除数组的第一个元素,并返回该元素。注意,该方法会改变原数组
|
|
- push和shift结合使用,就构成了“先进先出”的队列结构(queue)
unshift()
- unshift方法用于在数组的第一个位置添加元素,并返回添加新元素后的数组长度。注意,该方法会改变原数组
|
|
join()
- join方法以参数作为分隔符,将所有数组成员组成一个字符串返回。如果不提供参数,默认用逗号分隔
|
|
splice()
- splice方法用于删除原数组的一部分成员,并可以在被删除的位置添加入新的数组成员,返回值是被删除的元素。注意,该方法会改变原数组
- splice的第一个参数是删除的起始位置,第二个参数是被删除的元素个数。如果后面还有更多的参数,则表示这些就是要被插入数组的新元素
|
|
concat()
- concat方法用于多个数组的合并。它将新数组的成员,添加到原数组的尾部,然后返回一个新数组,原数组不变
|
|
reverse()
- reverse方法用于颠倒数组中元素的顺序,返回改变后的数组。注意,该方法将改变原数组
|
|
sort()
- sort方法对数组成员进行排序,默认是按照字典顺序排序。排序后,原数组将被改变
|
|
map()
- map方法对数组的所有成员依次调用一个函数,根据函数结果返回一个新数组
|
|
forEach()
- forEach方法与map方法很相似,也是遍历数组的所有成员,执行某种操作,但是forEach方法一般不返回值,只用来操作数据
|
|
filter()
- filter方法的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组
|
|
some(),every()
- 这两个方法类似“断言”(assert),用来判断数组成员是否符合某种条件
- some方法是只要有一个数组成员的返回值是true,则整个some方法的返回值就是true,否则false
- every方法则是所有数组成员的返回值都是true,才返回true,否则false
|
|
reduce(),reduceRight()
- reduce方法和reduceRight方法依次处理数组的每个成员,最终累计为一个值
- reduce是从左到右处理(从第一个成员到最后一个成员),reduceRight则是从右到左(从最后一个成员到第一个成员),其他完全一样
|
|
indexOf(),lastIndexOf()
- indexOf方法返回给定元素在数组中第一次出现的位置,如果没有出现则返回-1
|
|
code:用splice函数分别实现push、pop、shift、unshift方法
explain
|
|
code:写一个函数,操作数组,数组中的每一项变为原来的平方,在原数组上操作
explain
|
|
code:写一个函数,操作数组,返回一个新数组,新数组中只包含正数,原数组不变
explain
|
|
Date对象
- Date对象是JavaScript提供的日期和时间的操作接口。它可以表示的时间范围是,UTC时间的1970年1月1日00:00:00前后的各1亿天(单位为毫秒)
- UTC 世界标准时间
- CST 北京时间(东八区,比世界标准时间快(早)8小时,即如果北京时间是08:00:00,UTC时间是00:00:00)
new Date()
- Date还可以当作构造函数使用。对它使用new命令,会返回一个Date对象的实例
- 如果不加参数,生成的就是代表当前时间的对象
- 作为构造函数时,Date对象可以接受多种格式的参数
|
|
new Date(milliseconds)
- Date对象接受从1970年1月1日00:00:00 UTC开始计算的毫秒数作为参数
- Unix时间戳(单位为秒)作为参数,必须将Unix时间戳乘以1000
|
|
new Date(datestring)
- Date对象还接受一个日期字符串作为参数,返回所对应的时间,日期字符串的完整格式是“month day, year hours:minutes:seconds”
- 其他格式的日期字符串,也可以被解析
|
|
- 注意,在ES5(ES6取消)之中,如果日期采用连词线(-)格式分隔,且具有前导0,JavaScript会认为这是一个ISO格式的日期字符串,导致返回的时间是以UTC时区计算的
|
|
new Date(year, month [, day, hours, minutes, seconds, ms])
- Date对象还可以接受多个整数作为参数,依次表示年、月、日、小时、分钟、秒和毫秒
- 最少需要提供两个参数(年和月),其他参数都是可选的,默认等于0
- 如果只使用“年”这一个参数,Date对象会将其解释为毫秒数
|
|
- year:四位年份,如果写成两位数,则加上1900
- month:表示月份,0表示一月,11表示12月
- date:表示日期,1到31
- hour:表示小时,0到23
- minute:表示分钟,0到59
- second:表示秒钟,0到59
- ms:表示毫秒,0到999
|
|
日期的运算
- 类型转换时,Date对象的实例如果转为数值,则等于对应的毫秒数
- 如果转为字符串,则等于对应的日期字符串
- 两个日期对象进行减法运算,返回的就是它们间隔的毫秒数;进行加法运算,返回的就是连接后的两个字符串
|
|
Date对象的静态方法
Date.now()
- Date.now方法返回当前距离1970年1月1日 00:00:00 UTC的毫秒数(Unix时间戳乘以1000)
|
|
Date.parse()
- Date.parse方法用来解析日期字符串,返回距离1970年1月1日 00:00:00的毫秒数
|
|
Date.UTC()
- Date.UTC方法可以返回UTC时间(世界标准时间)
- 该方法接受年、月、日等变量作为参数,返回当前距离1970年1月1日 00:00:00 UTC的毫秒数
|
|
Date实例对象的方法
- get类:获取Date对象的日期和时间
- set类:设置Date对象的日期和时间
get类方法
- getTime():返回距离1970年1月1日00:00:00的毫秒数,等同于valueOf方法
- getDate():返回实例对象对应每个月的几号(从1开始)
- getDay():返回星期几,星期日为0,星期一为1,以此类推
- getYear():返回距离1900的年数
- getFullYear():返回四位的年份
- getMonth():返回月份(0表示1月,11表示12月)
- getHours():返回小时(0-23)
- getMilliseconds():返回毫秒(0-999)
- getMinutes():返回分钟(0-59)
- getSeconds():返回秒(0-59)
- getTimezoneOffset():返回当前时间与UTC的时区差异,以分钟表示,返回结果考虑到了夏令时因素
- getUTCDate()
- getUTCFullYear()
- getUTCMonth()
- getUTCDay()
- getUTCHours()
- getUTCMinutes()
- getUTCSeconds()
- getUTCMilliseconds()
|
|
set类方法
- setDate(date):设置实例对象对应的每个月的几号(1-31),返回改变后毫秒时间戳
- setYear(year): 设置距离1900年的年数
- setFullYear(year [, month, date]):设置四位年份
- setHours(hour [, min, sec, ms]):设置小时(0-23)
- setMilliseconds():设置毫秒(0-999)
- setMinutes(min [, sec, ms]):设置分钟(0-59)
- setMonth(month [, date]):设置月份(0-11)
- setSeconds(sec [, ms]):设置秒(0-59)
- setTime(milliseconds):设置毫秒时间戳
- setUTCDate()
- setUTCFullYear()
- setUTCHours()
- setUTCMilliseconds()
- setUTCMinutes()
- setUTCMonth()
- setUTCSeconds()
|
|
写一个函数getChIntv,获取从当前时间到指定日期的间隔时间
explain
|
|
把hh-mm-dd格式数字日期改成中文日期
explain
|
|
写一个函数,参数为时间对象毫秒数的字符串格式,返回值为字符串。假设参数为时间对象毫秒数t,根据t的时间分别返回如下字符串:
explain
|
|
正则表达式
>>三十分钟学会正则
JavaScript的DOM操作
- DOM是JavaScript操作网页的接口,全称为“文档对象模型”(Document Object Model)
- 它的作用是将网页转为一个JavaScript对象,从而可以用脚本进行各种操作(比如增删内容)
- DOM的最小组成单位叫做节点(node)。文档的树形结构(DOM树),就是由各种不同类型的节点组成
|
|
- 节点的类型有七种
- Document:整个文档树的顶层节点
- DocumentType:doctype标签(比如<!DOCTYPE html>)
- Element:网页的各种HTML标签(比如、等)
- Attribute:网页元素的属性(比如class=”right”)
- Text:标签之间或标签包含的文本
- Comment:注释
- DocumentFragment:文档的片段
- 除了根节点以外,其他节点对于周围的节点都存在三种关系
|
|
- 父节点关系(parentNode):直接的那个上级节点
- 子节点关系(childNodes):直接的下级节点
- 同级节点关系(sibling):拥有同一个父节点的节点
element.innerText和element.innerHTML
- innerText属性返回元素内包含的文本内容,而且会把元素内的标签元素去掉,在多层次的时候会按照元素由浅到深的顺序拼接其内容
- innerHTML属性返回该元素包含的 HTML 代码,包含了标签元素和文本
|
|
element.children和node.childNodes
- element.children是返回该元素下的所有子元素对象,不包括文本对象
- node.childNodes是返回该元素下的所有子对象,包括本文对象
|
|
查询元素常见的方法(查)、ES5的元素选择方法(查)
查询元素常见的方法
- document.getElementById()
- document.getElementsByClassName()
- document.getElementsByTagName()
- document.getElementsByName()
|
|
ES5的元素选择方法
- document.querySelector()
- document.querySelectorAll()
|
|
创建元素(增)、设置元素属性(改)、删除属性(删)
创建元素
- 创建元素节点:document.createElement(“div”)
- 创建文本节点:document.createTextNode(“你好”)
|
|
设置元素属性
- 获取元素的属性值:element.getAttribute(“id”)
- 设置元素的属性值:element.setAttribute(“align”,”center”)
- 生成一个新的属性对象节点:document.createAttribute(“my_attrib”)
|
|
删除元素属性(删)
- 删除元素属性:element.removeAttribute(“align”)
|
|
元素插入子元素(改)、删除元素的子元素(删)
元素插入子元素
- 在元素的末尾插入子元素:node.appendChild(span1)
- 在某个元素之前插入子元素:node.insertBefore(span2)
- 替换元素(接受两个参数:要插入的元素和要替换的元素):node.replaceChild(newSpan, divA)
|
|
|
|
删除元素的子元素
- 删除元素的子元素:node.removeChild(box)
|
|
element.classList的方法(HTML5api)
- 用于在元素中添加,移除及切换CSS类:element.classList
|
|
code:如何选中如下代码所有的li元素? 如何选中btn元素?
|
|
explain
|
|
JavaScript的事件
DOM0事件和DOM2事件处理方式
DOM0事件处理方式
- 通过JavaScript制定事件处理程序的传统方式;
- 把一个方法赋值给一个元素的事件处理程序属性,第四代web浏览器出现,至今所有浏览器都支持
|
|
- 一个事件处理程序只能对应一个处理函数,设置第二个事件,因为是赋值,所以第二个事件会覆盖第一个事件
DOM2事件处理方式
- DOM2级事件定义了两个方法用于处理指定和删除事件处理程序的操作
- 它们都接受三个参数(事件类型,事件处理方法,布尔参数[true,捕获阶段调用事件处理程序,默认false,事件冒泡阶段处理
])
|
|
attachEvent和addEventListener
- 参数个数不相同;attachEvent()接受两个参数,通过attachEvent()添加的事件处理程序会被添加到冒泡阶段;addEventListener()接受三个参数,第三个参数决定添加的处理事件是在捕获阶段还是冒泡阶段处理
- 第一个参数意义不同;addEventListener第一个参数是事件类型(比如click,load),而attachEvent第一个参数指明的是事件处理函数名称(onclick,onload)
- 事件处理程序的作用域不相同;addEventListener的作用域是元素本身,this是指的触发元素,而attachEvent事件处理程序会在全局变量内运行,this是window
- 为一个事件添加多个事件处理程序时,执行顺序不同;addEventListener添加会按照添加顺序执行,而attachEvent添加多个事件处理程序时顺序无规律
IE事件冒泡机制和DOM2事件流
IE的事件冒泡
- 事件开始时由最具体的元素接收,然后逐级向上传播到较为不具体的元素
DOM2事件流
- DOM2事件流包括三个阶段,事件捕获阶段,处于目标阶段,事件冒泡阶段,首先发生的是事件捕获,为截取事件提供机会,然后是实际目标接收事件,最后是冒泡阶段
阻止事件冒泡和阻止默认事件
- 事件发生以后,会生成一个事件对象,作为参数传给监听函数,称为event对象,包含与创建它的特定事件有关的属性和方法
阻止事件冒泡
- 标准浏览器:event.stopPropagation()
- IE浏览器:event.cancelBubble = true
|
|
阻止默认事件
- 标准浏览器:event.preventDefault()
- IE浏览器:e.returnValue = false
|
|
code:如下代码,要求当点击每一个元素li时控制台展示该元素的文本内容。不考虑兼容
|
|
explain
|
|
code:按如下要求,补全代码
- 当点击按钮开头添加时在li这里是/li元素前添加一个新元素,内容为用户输入的非空字符串
- 当点击结尾添加时在最后一个 li 元素后添加用户输入的非空字符串
- 当点击每一个元素li时控制台展示该元素的文本内容
|
|
explain
|
|
code:补全代码,要求:当鼠标放置在li元素上,会在img-preview里展示当前li元素的data-img对应的图片
|
|
explain
|
|
写一个通用的事件侦听器函数
|
|
JavaScript的闭包、定时器、BOM
闭包和立即执行函数(IIFE)
闭包(套路)
- 函数和函数内部能访问到的变量(也叫环境)的总和,就是一个闭包
- 创建闭包常见的方式就是在一个函数内部创建另一个函数,并返回当前函数作用域的变量,暴露出变量,让别人可以访问
|
|
立即执行函数(IIFE)
- 声明一个匿名函数,马上调用这个匿名函数
- 目的:1.是不必为函数命名,避免了污染全局变量;2.是IIFE内部形成了一个单独的作用域,可以封装一些外部无法读取的私有变量
|
|
code:下面的代码输出多少?修改代码让fnArri输出 i。使用两种以上的方法
|
|
explain
|
|
code:封装一个汽车对象,可以通过如下方式获取汽车状态
|
|
explain
|
|
定时器
- JavaScript提供定时执行代码的功能,叫做定时器(timer);主要由setTimeout()和setInterval()这两个函数来完成它们向任务队列添加定时任务
setTimeout()
- setTimeout函数用来指定某个函数或某段代码,在多少毫秒之后执行。它返回一个整数,表示定时器的编号,以后可以用来取消这个定时器
|
|
setInterval()
- setInterval函数的用法与setTimeout完全一致,区别仅仅在于setInterval指定某个任务每隔一段时间就执行一次,也就是无限次的定时执行
|
|
clearTimeout()、clearInterval()
- setTimeout和setInterval函数,都返回一个表示计数器编号的整数值,将该整数传入clearTimeout和clearInterval函数,就可以取消对应的定时器
|
|
运行机制
- setTimeout和setInterval的运行机制是,将指定的代码移出本次执行;必须等到本轮 Event Loop 的所有任务都执行完,才会开始执行
- 由于前面的任务到底需要多少时间执行完,是不确定的,所以没有办法保证,setTimeout和setInterval指定的任务,一定会按照预定时间执行
|
|
- setTimeout,指定100毫秒以后运行一个任务。但是,如果后面的veryLongTask函数(同步任务)运行时间非常长,过了100毫秒还无法结束,那么被推迟运行的someTask就只有等着,等到veryLongTask运行结束,才轮到它执行
|
|
- 第一行语句要求每隔1000毫秒,就输出一个2。但是,紧接着的语句需要3000毫秒才能完成,那么setInterval就必须推迟到3000毫秒之后才开始生效
setTimeout(f, 0)
- setTimeout(f, 0)的作用是,尽可能早地执行指定的任务。而并不是会立刻就执行这个任务
|
|
code:这段代码输出结果是
explain
|
|
code:这段代码输出结果是
explain
|
|
code:下面这段代码输出?如何输出delayer: 0, delayer:1…(使用闭包来实现)
|
|
explain
|
|
BOM
- BOM(Browser Object Model) 是指浏览器对象模型,是用于描述这种对象与对象之间层次关系的模型,浏览器对象模型提供了独立于内容的、可以与浏览器窗口进行互动的对象结构
元素的真实宽高
- getComputedStyle方法接受一个HTML元素作为参数,返回一个包含该HTML元素的最终样式信息的对象
|
|
URL的编码/解码方法
- 网页URL的合法字符分成两类,其他字符出现在URL之中都必须转义,规则是根据操作系统的默认编码,将每个字节转为百分号(%)加上两个大写的十六进制字母
|
|
编码
- encodeURI()
- encodeURIComponent()
|
|
解码
- decodeURI()
- decodeURIComponent()
|
|
- 访问这个URL,用encodeURI()函数,把中文或其他的特殊字符编码,让浏览器能识别整段URL
- 把这个URL放入到另一个URL中的时候,就要用 encodeURIComponent() 函数了,因为需要把 / = ? 这些特殊字符也编码,否则就容易出问题
判断用户的浏览器类型
|
|
JavaScript的AJAX
- AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和 XML 通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新。这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新
XMLHttpRequest对象
- XMLHttpRequest对象用来在浏览器与服务器之间传送数据
open方法
- open(method,url,async),规定请求的类型、URL 以及是否异步处理请求。
- method:请求的类型;GET 或 POST
- url:文件所在服务器的路径
- async:true(异步)或 false(同步)
同步和异步
- 第三个参数是true是异步,false是同步
- 当是异步时,浏览器把请求发送后就继续做自己的事,当onreadystatechange事件到来时说明服务端的数据来了,这时再处理数据。类似于一个节点绑定点击事件后就做后面的事,当用户点击了再执行绑定的处理函数
- 当是同步时,JavaScript 会等到服务器响应就绪才继续执行。如果服务器繁忙或缓慢,应用程序会挂起或停止。 当使用 async=false 时,不用编写 onreadystatechange 函数,把代码放到 send() 语句后面即可(不推荐用)
send方法
- send(string),将请求发送到服务器。
- string:仅用于 POST 请求
XMLHttpRequest对象的属性
onreadystatechange
- onreadystatechange属性指向一个回调函数,当readystatechange事件发生的时候,这个回调函数就会调用,并且XMLHttpRequest实例的readyState属性也会发生变化
readyState
- readyState是一个只读属性,用一个整数和对应的常量,表示XMLHttpRequest请求当前所处的状态,一般来说,只研究4
- 0: 请求未初始化
- 1: 服务器连接已建立
- 2: 请求已接收
- 3: 请求处理中
- 4: 请求已完成,且响应已就绪
status
- status属性为只读属性,表示本次请求所得到的HTTP状态码,它是一个整数。一般来说,如果通信成功的话,这个状态码是200
- 200, OK,访问正常
- 301, Moved Permanently,永久移动
- 302, Move temporarily,暂时移动
- 304, Not Modified,未修改
- 307, Temporary Redirect,暂时重定向
- 401, Unauthorized,未授权
- 403, Forbidden,禁止访问
- 404, Not Found,未发现指定网址
- 500, Internal Server Error,服务器发生错误
responseText
- responseText属性返回从服务器接收到的字符串,该属性为只读
- 如果服务器返回的数据格式是JSON,就可以使用responseText属性
|
|
Ajax和form交互的区别
- AJAX 是前端向后端发出数据请求,后端返回需要的数据,前端用这些数据改写HTML页面,页面不会刷新
- form 是前端向后端发出数据请求,后端把需要的数据填入HTML模板(.ejs文件)创建新的HTML,再把新的HTML发回给前端,这样前端的页面就会做一次刷新
前后端开发联调及mock数据
前后端开发联调
- 接口(路径)名称,统一命名,定制规范,拟定命名表(‘/getFriends’)
- 接口请求方式(post/get)
- 请求参数的名称、数量、对应值(‘ruoyu’、’hunger’)
- 返回响应数据格式(json/text)
mock数据
- 在 node.js 环境下安装 server-mock (npm install -g server-mock)
- 在项目文件夹下,创建 router.js 文件,写好对应接口的响应函数,创造一些假数据
- 启动server-mock:server start
|
|
AJAX数据锁
- 点击按钮,使用ajax获取数据,添加一个锁(true、false),防止用户在数据到来之前防止重复点击
|
|
code:封装一个ajax函数,能通过如下方式调用.后端在本地使用server-mock来mock数据
|
|
效果图
explain
前端代码
|
|
后端代码
|
|
code:ajax实现点击加载更多的功能,后端在本地使用server-mock来模拟数据
效果图
explain
前端代码
|
|
后端代码
|
|
跨域
- 跨域就是不同域下的接口交互
同源策略(Same origin Policy)
- 浏览器出于安全方面的考虑,只允许与本域下的接口交互。不同源的客户端脚本在没有明确授权的情况下,不能读写对方的资源
- 同协议:如都是http或者https
- 同域名:如都是http://baidu.com/a.html 和 http://baidu.com/b.html
- 同端口:如都是80端口
前端代码
|
|
后端代码
|
|
效果图
跨域的实现方式
- JSONP
- CORS
- 降域
- postMessage
JSONP
- 定义数据处理函数_fun
- 创建script标签,src的地址执行后端接口,最后加个参数callback=_fun
- 服务端在收到请求后,解析参数,计算返还数据,输出 fun(data) 字符串
- fun(data)会放到script标签做为js执行。此时会调用fun函数,将data做为参数
前端代码
|
|
后端代码
|
|
- jsonp就是获取一段代码,用js去执行,前端向后端发送一个参数,后端用这个参数封装数据,发回来,前端再执行
- jsonp需要前后端配合,后端同意才能跨域,没有安全问题
效果图
CORS
- 全称为 Cross Origin Resource Sharing,跨域资源共享,是一种ajax跨域请求资源的方式,支持现代浏览器,IE支持10以上
- 在后端的响应头添加一个Access-Control-Allow-Origin属性,属性的值是允许的域名。它的好处是前端的请求就是ajax,不需要修改,只要后端开访问权限即可,很方便
前端代码
|
|
后端代码
|
|
效果图
降域
- 页面ifram内部嵌套一个网页,如果域名不同,就不能互相操作,因有跨域问题,如果域名的后缀是一样的,只是前面不一样,可以用降域来解决
前端index代码
|
|
前端index1代码
|
|
postMessage
- postMessage()方法允许来自不同源的脚本采用异步方式进行有限的通信,可以实现跨文本档、多窗口、跨域消息传递
- postMessage(data,origin)方法接受两个参数1.data:要传递的数据2.origin:字符串参数,指明目标窗口的源,协议+主机+端口号[+URL]
前端index代码
|
|
前端index1代码
|
|