js基础学习笔记

261 阅读26分钟
                                             ## js中零散知识点
  1. 控制浏览器弹出一个警告框 alert()

  2. document.write()可以向<body>中输出一个内容。

  3. console.log向控制台输出一个内容

  4. js代码是从上到下一行一行执行的

  5. <script>标签一旦用于引入外部文件,就不能再编写代码了,即使编写了浏览器也会忽略,如需要则可以再创建一个新的<script>标签用于编写内部代码。

  6. 可以通过Math.sqrt()对一个数进行开方。

  7. 基本数据类型都是单一的值,值和值之间没有任何的联系。

  8. 可以通过debug断点的形式查看代码的执行和整个程序的内存结构。

js编写位置

  1. 可以将js代码编写到标签的onclick属性中,当我们点击标签时,js代码才会执行。(虽然可以写在标签的属性中,但是他们属于结构与行为耦合,不方便维护,不推荐使用)
  2. 可以将js代码写在超链接的href属性中,这样当点击超链接时,会执行js代码。
  3. 可以将js代码编写到<script>标签中
  4. 可以将js代码编写到外部js文件中,然后通过<script>标签引入,写到外部文件中可以再不同的页面中同时引用,也可以利用到浏览器的缓存机制(推荐使用的方式)

js基本语法

  1. 多行注释
/*

* 注释中的内容不会被执行,但是可以在源代码中查看,要养成良好的编写注释的习

* 惯,也可以通过注释来对代码进行一些简单的调试

*/
  1. 单行注释
// 只会对一行中注释后面的内容起作用
  1. js中严格区分大小写

  2. js中每一条语句以分号()结尾

    • 如果不写分号,浏览器弧自动添加,但是会消耗一些系统资源,而且有些时候,浏览器会加错分号,所以在开发中分号必须写。
  3. js中会忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化。

字面量和变量

  1. 字面量,都是一些不可变的值。字面量都是可以直接使用的,但是我们一般都不会直接使用字面量。

  2. 变量,可以用来保存字面量,而且变量的值是可以任意改变的。变量更加方便我们使用,所以在开发中都是通过变量去保存一个字面量,而很少直接使用字面量。可以通过变量对字面量进行描述

  3. 声明变量

    • 在js中使用var关键字来声明一个变量

      例:var a;

    • 为变量赋值

      a=123;

    • 也可以同时声明并赋值

      var b=0;

标识符

  1. 在js中所有的可以由我们自主命名的都可以称为是标识符

    • 例如:变量名,函数名,属性名都属于标识符
  2. 命名一个标识符时需要遵守如下规则:

    1.标识符中可以含有字母,数字 _ $

    2.标识符不能以数字开头

    3.标识符不能是ES中的关键字或保留字

    4.标识符一般都采用驼峰命名法

  3. 首字母小写,每个单词的开头字母大写,其余字母小写

    例:helloWorld

  4. js底层保存标识符时实际上采用的Unicode编码,所以理论上讲,所有的utf-8中含有的内容都可以作为标识符。但是千万不要用中文起名。

数据类型

  1. 数据类型指的是字面量的类型

  2. 在js中一共有六中数据类型

    String 字符串

    Number 数值

    Boolean 布尔值

    Null 空值

    Undefined 未定义

    Object 对象

    其中String,Number,Boolean,Null,Undefined属于基本数据类型,而Object属于引用数据类型。

  3. String字符串

  • 在js中字符串需要使用引号引起来

  • 使用双引号或单引号都可以,但是不要混着用

  • 引号不能嵌套,双引号不能放双引号,单引号不能放单引号。

  1. 在字符串中可以使用\作为转义字符,当表示一些特殊符号时可以使用\进行转义。

     \" 表示“
    
     \' 表示‘
    
     \n 表示换行
    
     \t 表示制表符
    
     \\ 表示\
    
  2. Number

    • 在js中所有的数值都是Number类型,

    • 包括整数和浮点数(小数)

  3. 可以使用改一个运算符typeof来检查一个变量的类型

    • 语法:typeof 变量

    • 检查字符串时,会返回string

    • 检查数值时,会返回number

  4. js中可以表示的数字的最大值

     Number.MAX_VALUE
    
  5. 如果使用number表示的数字超过了最大值,则会返回一个Infinity(表示正无穷)

  6. 使用typeof检查Infinity返回number

  7. NaN 是一个特殊的数字,使用typeof检查NaN,返回number

  8. Number.MIN_VALUE 大于0的最小数

  9. 在js中整数的运算基本可以保证精确

  10. 如果使用js进行浮点元素,可能得到一个不精确的结果,所以千万不要使用js进行对精确度要求比较高的运算。

  11. Boolean布尔值

    • 布尔值只有两个,主要用来做逻辑判断

      • true表示真

      • false表示假

    • 使用typeof检查一个布尔值时,会返回boolean

  12. Null类型

    • Null类型的值只有一个,就是null

    • null这个值专门用来表示一个为空的对象

    • 使用typeof检查一个Null值时,会返回object

  13. Undefined(未定义)类型的值只有一个,就是undefined

  14. 当声明一个变量,但是并不给变量赋值时,它的值就是undefined

  15. 使用typeof检查一个Undefined时会返回undefined

强制类型转换

  1. 强制类型转换指将一个数据类型强制转换为其他的数据类型

  2. 类型转换主要指,将其他的数据类型转换为String Number Boolean

  3. 将其他的数据类型转换为String

    方式一:

    • 调用被转换数据类型的toString()方法

    • 调用xxx的yyy( )方法,就是xxx.yyy( )

    • 但是注意:nullundefined这两个值没有toString方法,如果调用他们的方法,会报错。

    方式二:

    • 调用String()函数,并将被转换的数据作为参数传递给函数
  4. 使用String()函数做强制类型转换时,对于NumberBoolean实际上就是调用的toString()方法,但是对于nullundefined就不会调用toString()方法,他会将null直接转换为“null”,将undefined直接转换为“undefined”

  5. 将其他的数据类型转换为Number

    方式一:

    • 使用Number()函数

    • 字符串 --> 数字

      1. 如果是纯数字的字符串,则直接将其转换为数字

      2. 如果字符串中有非数字的内容,则转换为NaN

      3. 如果字符串是一个空串或者是一个全是空格的字符串,则转换为0

    • 布尔 -->数字

      true 转成 1

      false转成 0

    • null --> 数字 0

    • undefined --> 数字 NaN

    方式二:

    • 这种方式专门用来对付字符串

    • parseInt()把一个字符串转换为一个整数

      parseInt()可以将一个字符串中的有效的整数内容取出来,然后转换为Number类型

    • parseFloat()把一个字符串转换为一个浮点数

      parseFloat()可以将一个字符串中的有效的小数内容取出来,然后转换为Number类型

    如果对非String使用parseInt()parseFloat(),它会先将其转换为String,然后再操作

  6. 将其他的数据类型转换为Boolean

    • 使用Boolean()函数

    • 数字 --> 布尔

      除了0和NaN,其余的都是true

    • 字符串 --> 布尔

      除了空串,其余的都是true

    • nullundefined都会转换为false

    • 对象也会转换为true

其他进制的数字

  1. 在js中,如果需要表示16进制的数字,则需要以0x开头

  2. 如果需要表示8进制的数字,则需要 以0 开头

  3. 如果需要表示2进制数字,则需要以0b开头,但是并不是所有的浏览器都支持

  4. 注意:像“070”这种字符串,有些浏览器会当成8进制解析,有些会当成10进制解析。可以在parseInt()中传递一个第二个参数,来指定数字的进制。

运算符

  1. 运算符也叫操作符,通过运算符可以对一个或多个值进行运算,并获取运算结果。比如:typeof就是运算符,可以来获得一个值的类型。它会将该值的类型以字符串的形式返回。

  2. 算数运算符

    1. 当对非Number类型的值进行运算时,会将这些值转换为Number然后再运算

    2. 任何值和NaN作运算都得NaN

    3. +可以对两个值进行加法运算,并将结果返回。如果对两个字符串进行加法运算,则会做拼串。会将两个字符串拼接为一个字符串,并返回。任何的值和字符串做加法运算,都会转换为字符串,并做拼串操作

    4. 我们可以利用这个特点,来将一个任意的数据类型转换为String,只需要为任意的数据类型+ 一个"" 即可将其转换为String。这是一种隐式的类型转换,由浏览器自动完成,实际上它也是调用String()函数。

    5. -可以对两个值进行减法运算,并将结果返回

    6. *可以对两个值进行乘法运算

    7. /可以对两个值进行除法运算

    8. 任何值做 - * /运算时都会自动转换为Number,可以利用这一特点做一隐式的类型转换,可以通过一个值 -0 *1 /1来将其转换为Number,原理和Number()函数一样,使用起来更加简单

    9. %可以对两个值进行取余运算

  3. 一元运算符

    • 只需要一个操作数

    • 正号 不会对数字产生任何影响

    • 负号 可以对数字进行符号取反

    对于非number类型会先转换为Number,然后再运算

    可以对一个其他的数据类型使用+,来将其转换为Number,原理和Number()函数一样

  4. 逻辑运算符

    js中为我们提供了三种逻辑运算符

      • !可以用来对一个值进行非运算

      • 所谓非运算就是对一个布尔值进行取反操作

      truefalsefalsetrue

      • 如果对一个值进行两次取反,它不会变化

      • 如果对非布尔值进行运算,则会将其转换为布尔值,然后再取反。

      所以我们可以利用该特点,来将一个其他的数据类型转换为布尔值

      可以为一个任意数据类型取两次反,来将其转换为布尔值,原理和Boolean()函数一样。

    1. &&

      • &&可以对符号两侧的值进行与运算

      • 只有两端的值都为true时,才会返回true。只要有一个false就会返回false

      • js中的与是一个短路的与,如果第一个值是false,则不再检查第二个值

      • 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值

      • 规则:

        1.如果第一个值为false,则返回第一个值

        2.如果第一个值为true,则返回第二个值

    2. ||

    • ||可以对符号两侧的值进行或运算
      • 只有两端都是false时,才会返回false。只要有一个true,就会返回true

      • js中的或是一个短路的或,如果第一个值是true,则不再检查第二个值

      • 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值

      • 规则:

      1. 如果第一个值为true,则返回第一个值

      2. 如果第一个值为false,则返回第二个值

  5. && || 非布尔值的情况

    • 对于非布尔值进行与或运算时,会先将其转换为布尔值,然后再运算

    • 与运算:

      如果第一个值都为true,则返回第二个值

      如果第一个值为false,则返回第一个值

    • 或运算:

      如果第一个值为true,则直接返回第一个值

      如果第一个值为false,则直接返回第二个值

  6. 赋值运算符

    =

    • 可以将符号右侧的值赋值给左侧变量

    +=

    • a += 5 相当于 a = a+5

    • var str = "hello"; str += "world";

    -=

    • a -= 5 相当于 a = a-5

    *=

    • a *= 5 相当于 a = a*5

    /=

    • a /= 5 相当于 a = a/5

    %=

    • a %= 5 相当于 a = a%5
  7. 关系运算符

    • 关系运算符用来比较两个值之间的大小关系的

    >

    >=

    <

    <=

    • 关系运算符的规则和数学中一致,用来比较两个值之间的关系,如果关系成立则返回true,关系不成立则返回false

    • 如果比较的两个值是非数值,会将其转换为Number然后再比较。

    • 如果比较的两个值都是字符串,此时会比较字符串的Unicode编码,而不会转换为Number。比较字符编码时是一位一位进行比较的,如果两位一样则比较下一位,所以借用它对英文进行排序。比较中文是没有意义的

    • 注意:在比较两个字符串型的数字时,一定一定要转型。

    • 任何值和NaN做任何比较都是false

  8. 相等运算符

    1. 用来比较两个值是否相等,如果相等会返回true,否则返回false

    ==

    • 相等,判断左右两个值是否相等,如果相等返回true,如果不等返回false

    • 相等会自动对两个值进行类型转换,如果对不同的类型进行比较,会将其转换为相同的类型然后再比较,转换后相等它也会返回true

    • underfined 衍生自null,所以这两个值做相等判断时,会返回true

    • NaN不和任何值相等,包括他本身

    !=

    • 不等,判断左右两个值是否不等,如果不等则返回true,如果相等则返回false

    • 不等也会做自动的类型转换,转换后相等它也会返回true

    ===

    • 全等,判断左右两个值是否全等,它和相等类似,只不过它不会进行自动的类型转换,

    如果两个值的类型不同,则直接返回false

    !==

    • 不全等,和不等类似,但是它不会进行自动的类型转换,如果两个值的类型不同,它会直接返回true

    特殊的值:

    • nullundefined, 由于undefined衍生自null,所以null == undefined 会返回true。但是 null === undefined 会返回false

    • NaN 不与任何值相等,报告它自身 NaN == NaN //false

    • 判断一个值是否是NaN,使用isNaN()函数,如果该值是NaN则返回true,否则返回false

  9. 三元运算符:

    ?:

    • 语法:条件表达式?语句1:语句2;

    • 执行流程:

    先对条件表达式求值判断,

    如果判断结果为true,则执行语句1,并返回执行结果。

    如果判断结果为false,则执行语句2,并返回执行结果。

    • 如果条件的表达式的求值结果是一个非布尔值,会将其转换为布尔值然后再进行运算。
  10. 运算符

    使用可以分割多个语句,一般可以在声明多个变量时使用。 优先级:

    • 和数学中一样,JS中的运算符也是具有优先级的,比如 先乘除 后加减 先与 后或

    • 具体的优先级可以参考优先级的表格,在表格中越靠上的优先级越高,优先级越高的越优先计算,优先级相同的,从左往右计算。

    • 优先级不需要记忆,如果越到拿不准的,使用()来改变优先级。

自增和自减

  1. 自增 ++

    • 通过自增可以是变量在自身的基础上增加1

    • 对一个变量自增以后,原变量的值会立即自增1

    • 自增分成两种,后++(a++)前++(++a)

      无论是a++ 还是++a,都会立即使原变量的值自增1

    不同的是a++++a的值不同

    a++ 的值等于原变量的值(自增前的值)

    ++a的值等于新值(自增后的值)

  2. 自减 --

    • 通过自减可以是变量在自身的基础上减1

    • 自减分成两种:后--(a--)前--(--a)

      无论a--还是--a,都会立即使原变量的值自减1

    不同的是a--和--a的值不同

    a--的值等于原变量的值(自减前的值)

    --a的值等于新值(自减后的值)

Unicode编码

在字符串中使用转义字符输入Unicode编码

\u四位编码

在网页中使用Unicode编码

&#编码,这个的编码需要的是10进制。

代码块

  1. 程序是由一条一条语句构成的

  2. 语句是按照自上向下的顺序一条一条执行的

  3. 在js中可以使用{}来为语句进行分组,同一个{}中的语句称为是一组语句,他们要么都执行,要么都不执行,一个{}中的语句称为代码块,在代码块的后面就不用再编写;了。

  4. js中的代码块,只具有分组的作用,没有其他的用途

  5. 代码块的内容,在外部是完全可见的。

流程控制语句

  1. 程序都是自上向下的顺序执行的,通过流程控制语句可以改变程序执行的顺序,或者反复的执行某一段的程序。

  2. 分类:

    1. 条件判断语句

    2. 条件分支语句

    3. 循环语句

  3. 条件判断语句

    • 条件判断语句也称为if语句,if语句中的条件表达式中千万不要写一个=,一个=是赋值。

    • if语句只能控制紧随其后的那个语句 ,如果希望if语句可以控制多条语句可以将这些语句统一放到代码块中。if语句后的代码块不是必须的,但是在开发中尽量写代码块,即使代码块中只有一条语句。

  • 语法一:
if(条件表达式){

语句...

}
  • 执行流程:

    if语句执行时,会先对条件表达式进行求值判断,如果值为true,则执行if后的语句;如果值为false,则不执行

  • 语法二:

if(条件表达式){

语句...

}else{

语句...

}
  • 执行流程:

    if...else语句执行时,会对条件表达式进行求值判断,如果值为true,则执行if后的语句;如果值为false,则执行else后的语句

  • 语法三:

if(条件表达式){

语句...

}else if(条件表达式){

语句...

}else if(条件表达式){

语句...

}else if(条件表达式){

语句...

}else{

语句...

}
  • 执行流程

  • if...else if...else语句执行时,会自上至下依次对条件表达式进行求值判断,如果判断结果为true,则执行当前if后的语句,执行完成后语句结束。如果判断结果为false,则继续向下判断,直到找到为true的为止。如果所有的条件表达式都是false,则执行else后的语句,该语句中,只会有一个代码块被执行,一旦代码块执行了,则直接结束语句。

  1. 条件分支语句
  • switch语句

  • 语法:

switch(条件表达式){

case 表达式:

语句...

break;

case 表达式:

语句...

break;

case 表达式:

语句...

break;

default:

语句...

break;

}
  • 执行流程:

  • switch...case...语句在执行时,会依次将case后的表达式的值和switch后的表达式的值进行全等比较,如果比较结果为false,则继续向下比较。如果比较结果为true,则从当前case处开始向下执行代码(当前case后的所有的代码都会执行)。我们可以在case后边跟着break,这样可以确保只会执行当前case后的语句,而不会执行其他的case

  • 如果所有的case判断结果都为false,则从default处开始执行代码。

  • break

    使用break可以退出switch语句

  • switch语句和if语句的功能实际上是有重复的,使用switch可以实现if的功能,同样使用if也可以实现switch的功能,所以我们使用时,可以根据自己的习惯选择。

  1. 循环语句
  • 通过循环语句可以反复执行某些语句多次

  • while循环

  • 语法:

while(条件表达式){

语句...

}
  • 执行流程:

while语句在执行时,会先对条件表达式进行求值判断,如果判断结果为false,则终止循环;如果判断结果为true,则执行循环体;循环体执行完毕,继续对条件表达式进行求值判断,依此类推。

  • 向这种将条件表达式写死为true的循环,叫做死循环。该循环不会停止,除非浏览器关闭

  • 创建一个循环,往往需要三个步骤,

    1. 创初始化一个变量

    2. 在循环中设置一个条件表达式

    3. 定义一个更新表达式,每次更新初始化变量

  • do...while循环

  • 语法:

do{

语句...

}while(条件表达式)

  • 执行流程

    • do...while在执行时,会先执行do后的循环体,然后在对条件表达式进行判断,

    • 如果判断判断结果为false,则终止循环。

    • 如果判断结果为true,则继续执行循环体,依此类推

  • while的区别:

    while:先判断后执行

    do...while: 先执行后判断

    • do...while可以确保循环体至少执行一次。
  • for循环

  • 语法:

for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){

③语句...

}
  • 执行流程:

    首先执行①初始化表达式,初始化一个变量(初始化表达式只会执行一次),

    然后对②条件表达式进行求值判断,如果为false则终止循环

    如果判断结果为true,则执行③循环体

    循环体执行完毕,执行④更新表达式,对变量进行更新。

    更新表达式执行完毕重复②

  • 死循环

    while(true){}

    • 如果在for循环中不写任何的表达式,只写两个;;此时循环是一个死循环会一直执行下去,慎用

    for(;;){ }

  • break关键字可以用来退出switch或循环语句

    不能在if语句中使用breakcontinue

    多个循环嵌套的情况下,break只对离它最近的循环起作用

    可以为循环语句创建一个label,来表示当前的循环

    label:循环语句

    使用label语句时,可以在break后跟着一个label,这样break将会结束指定的循环,而不是最近的。

  • continue关键字可以用来跳过当次循环

    同样continue也是默认只会对离他最近的循环起作用。

提示框prompt()

  1. prompt()函数可以弹出一个提示框,该提示框中会带有一个文本框

  2. 用户可以在文本框中输入一段内容,该函数需要一个字符串作为参数

  3. 该字符串将会作为提示框的提示文字

  4. 用户输入的内容将会作为函数的返回值返回,可以定义一个变量来接收该内容,

  5. prompt()函数的返回值是String类型的。

定时器

  1. 开启计时器

    console.time(“计时器的名字”)可以用来开启一个计时器

    他需要一个字符串作为参数,这个字符串将会作为计时器的标识

  2. 终止计时器

    console.timeEnd()用来停止一个计时器,需要一个即时起的名字作为参数.

对象object

  1. 对象属于一种复合的数据类型,在对象中可以保存多个不同数据类型的属性。

  2. 对象的分类

    1. 内建对象

      • 由ES标准中定义的对象,在任何的ES的实现中都可以使用

      • 比如:MAth String Number....

    2. 宿主对象

    -由js的运行环境提供的对象,目前来讲主要指由浏览器提供的对象

    • 比如BOM DOM

    1. 自定义对象

    • 由开发人员自己创建的对象
  3. 创建对象

    • 方式一:

      • 使用new关键字调用的函数,是构造函数constructor

      构造函数是专门用来创建对象的函数

      • var obj = new Object();
    • 方式二:

      • var obj = {};
  4. 向对象中添加属性

    • 语法:

      对象.属性名 = 属性值;

      对象["属性名"] = 属性值;

  5. 读取对象中的属性

    • 语法:

      对象.属性名

      对象["属性名"]

    • 如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined

  6. 修改对象的属性值

    • 语法:

      对象.属性名 = 新值

  7. 删除对象中的属性

    • 语法:

      delete 对象.属性名

      delete 对象["属性名"]

  8. 向对象中添加属性

    • 对象的属性名没有任何要求,不需要遵守标识符的规范,但是在开发中,尽量按照标识符的要求去写。

    • 属性值也可以任意的数据类型。

    • 如果要使用特殊的属性名,不能采用.的方式来操作

    需要使用另一种方式:

    • 语法:

      对象["属性名"]=属性值

      读取时也需要采用这种方式

    • 使用[ ]这种形式去操作属性,更加的灵活,在[ ]中可以直接传递一个变量,这样变量值是多少就会读取那个属性。

  9. 属性值

    js对象的属性值,可以是任意的数据类型,甚至也可以是一个对象

    • 使用in检查对象中是否含有指定属性

    • 语法:"属性名" in 对象

      • 如果在对象中含有该属性,则返回true,如果没有则返回false
  10. 枚举对象中的属性

    使用for ... in 语句

    • 语法:

      for(var 变量 in 对象){ }

      for... in语句,对象中有几个属性,循环体就会执行几次

      每次执行时,会将对象中的一个属性的名字赋值给变量

  11. 使用对象字面量,在创建对象时直接向对象中添加属性。对象字面量的属性名可以加引号也可以不加,建议不加,如果要使用一些特殊的名字,则必须加引号,属性名和属性值是一组一组的名值对结构,名和值之间使用:连接,多个名值对之间使用,逗号隔开。

    如果一个属性之后没有其他的属性了,就不要写逗号了

    • 语法:
        var obj = {
            属性名:属性值,
            属性名:属性值,
            属性名:属性值,
            属性名:属性值
        }
    
    
  12. 基本数据类型和引用数据类型

  • 基本数据类型

    String Number Boolean Null Undefined

  • 引用数据类型

    Object

  • js中的变量都是保存到栈内存中的

  • 基本数据类型的数据在栈内存中存储,变量是直接保存的它的值。

  • 变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。

  • 引用数据类型的数据是保存在堆内存中,每创建一个新的对象,就会在堆内存中开辟出一个新的内存空间,变量是保存的对象的引用(内存地址)。

  • 如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。

  • 比较两个变量时,对于基本数据类型,比较的就是值,对于引用数据类型比较的是地址,地址相同才相同。

函数(Function)

  • 函数也是一个对象,也具有普通对象的功能

  • 函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码

  • 使用typeof检查一个函数时会返回function

  • 创建函数

    可以将要封装的代码以字符串的形式传递给构造函数

    在实际开发中很少使用构造函数的

    var fun = new Function();

    封装到函数中的代码不会立即执行

    函数中的代码会在函数调用的时候执行

  • 函数声明

    function 函数名([形参1,形参2...形参N]){

    语句...

    }
  • 函数表达式
    var 函数名 = function([形参1,形参2...形参N]){

    语句...

    };
  • 调用函数
函数对象([实参1,实参2...实参N]);

fun() sum() alert() Number() parseInt()

  • 当我们调用函数时,函数中封装的代码会按照编写的顺序执行

形参和实参

  • 形参:形式参数

  • 定义函数时,可以在函数的()中定义一个或多个形参,形参之间使用,隔开

    定义形参就相当于在函数内声明了对应的变量但是并不赋值,形参会在调用时才赋值。

  • 实参:实际参数

  • 调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参,

    调用函数时JS解析器不会检查实参的类型和个数,可以传递任意数据类型的值。所以要注意,是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查。

    如果实参的数量大于形参,多余实参将不会赋值,

    如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined

  • 函数返回值,就是函数执行的结果。

  • 使用return 来设置函数的返回值。

  • 语法:return 值;

  • 该值就会成为函数的返回值,可以通过一个变量来接收返回值

  • return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出。

  • return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。

  • 如果return后不跟值,或者是不写return则函数默认返回undefined

  • break、continue和return

    • break 退出循环

    • continue 跳过当次循环

    • return 退出函数

  • 参数,函数的实参可以是任意的数据类型,也可以是一个对象,然后通过对象传递。

  • 函数名()

    • 调用函数

    • 相当于使用的函数的返回值

  • 函数名

    • 函数对象

    • 相当于直接使用函数对象

  • 立即执行函数

    函数定义完,立即被调用,这种函数叫做立即执行函数

    立即执行函数往往只会执行一次,

    语法:将匿名函数用()括起来,然后在后面加个();表示立即执行,有参数的时候,在后面的()中可以添加参数。

  • 方法(method)

    • 可以将一个函数设置为一个对象的属性,

    当一个对象的属性是一个函数时,我们称这个函数是该对象的方法。

    但是只是名称上的区别,没有本质的差别

    • 对象.方法名();

    • 函数名();

作用域

  • 作用域指一个变量的作用的范围

  • 在js中一共有两种作用域:

    1. 全局作用域

      • 直接编写在script标签中的js代码,都在全局作用域

      • 全局作用域在页面打开时创建,在页面关闭时销毁。

      • 在全局作用域中有一个全局对象window,我们可以直接使用

      它代表的是一个浏览器的窗口,它由浏览器创建

      • 在全局作用域中,

        创建的变量都会作为window对象的属性保存

        创建的函数都会作为window对象的方法保存

      • 全局作用域中的变量都是全局变量

        在页面的任意的部分都可以访问到

    2. 函数作用域

      • 函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域,他们之间是相互独立的。

      • 函数作用域在函数执行时创建,在函数执行结束时销毁。

      • 在函数作用域中可以访问到全局作用域的变量

      • 在函数作用域中创建的变量,不能在全局中访问。

      • 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,如果找到了则使用,找不到则继续向上找,一直会找到全局作用域,如果全局作用域中依然没有找到,则会报错ReferenceError

      • 在函数作用域中如果想要访问全局的变量,可以使用window对象

    3. 变量的声明提前

      • 在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。

        所以我们可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。

      • 在函数作用域中,也具有声明提前的特性,使用var关键字声明的变量会在函数所有的代码执行前被声明,

        如果没有使用var关键字声明变量,则变量会变成全局变量

        定义形参就相当于在函数作用域中声明了变量

    4. 函数的声明提前

      • 使用函数声明形式创建的函数function 函数(){ }

        它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数

      • 使用函数表达式创建的函数,不会被声明提前,所以不能在声明前调用。

this(上下文对象)

  • 我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。

  • 使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。

  • this的不同的情况:

    1. 以函数的形式调用时,thiswindow

    2. 以方法的形式调用时,this就是调用方法的对象(谁调用方法this就是谁)

    3. 以构造函数的形式调用时,this就是新创建的对象。

使用工厂方法创建对象

  • 通过该方法可以大批量的创建对象

    1. 创建带参数一个函数声明

    2. 在函数声明中创建一个新的对象

    3. 向对象中添加属性

    4. 将新的对象返回

    然后创建变量调用这个函数声明,直接传实参就可以实现函数。

  • 使用工厂方法创建的对象,使用的构造函数都是Object

  • 所以创建的对象都是Object这个类型,导致我们无法区分出多种不同类型的对象。

构造函数

  • 构造函数是专门用来创建对象的函数

  • 一个构造函数我们也可以称为一个类

  • 通过一个构造函数创建的对象,我们称该对象是这个构造函数的实例(这个类的实例)

  • 通过同一个构造函数创建的对象,我们称为一类对象

  • 构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写,且他的调用方式不同,如果直接调用,它就是一个普通函数;如果使用new来调用,则它就是一个构造函数

  • 在构造函数中不要直接添加一个方法,这样创建一个实例就会创建一个一模一样的方法,消耗资源,可以将方法在全局作用域中定义,然后在构造函数中引用该方法。但是将函数定义在全局作用域,污染了全局作用域的命名空间,而且定义在全局作用域中也很不安全,最好的方式是在构造函数的原型对象中添加该方法。

  • 例子:

function Person(){

}
  • 构造函数的执行流程:

    1. 立刻创建一个新的对象

    2. 将新的对象作为函数的上下文对象(this),在构造函数中可以使用this来引用新建的对象

    3. 执行函数中的代码

    4. 将新建的对象作为返回值返回

  • instanceof 用来检查一个对象是否是一个类的实例

    • 语法:对象 instanceof 构造函数

    • 如果该对象时构造函数的实例,则返回true,否则返回false

  • Object是所有对象的祖先,所以任何对象和Objectinstanceof都会返回true

原型(prototype)

  • 创建一个函数以后,解析器都会默认在函数中添加一个属性prototype

  • prototype属性指向的是一个对象,这个对象我们称为原型对象。

  • 当函数作为构造函数使用,它所创建的对象中都会有一个隐含的属性执行该原型对象。

  • 这个隐含的属性可以通过对象.__proto__来访问。

  • 原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。

  • 我们可以将对象中共有的属性和方法统一添加到原型对象中,这样我们只需要添加一次,就可以使所有的对象都可以使用。

  • 当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,如果在自身中找到了,则直接使用。如果没有找到,则去原型对象中寻找,如果找到了则使用,如果没有找到,则去原型的原型中寻找,依此类推。直到找到Object的原型为止,Object的原型的原型为null,如果依然没有找到则返回undefined

  • 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了。

  • 使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true

  • hasOwnProperty()

    • 这个方法可以用来检查对象自身中是否含有某个属性

    • 语法:对象.hasOwnProperty("属性名")

    • 使用该方法只有当对象自身中含有属性时,才会返回true

  • 当我们直接在页面中打印一个对象时,实际上是输出的对象的toString()方法的返回值,如果我们希望再输处对象时不输出[object Object],可以为对象添加一个toString()方法,或者在构造函数的原型中修改toString()方法。

垃圾回收(GC)

  • 程序运行过程中也会产生垃圾,垃圾积攒过多以后,会导致程序运行的速度过慢,所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾。

  • 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须进行清理。

  • 在js中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作

  • 我们需要做的只是要将不再使用的对象设置null即可。

数组(Array)

  • 数组也是一个对象,是一个用来存储数据的对象

  • Object类似,但是它的存储效率比普通对象要高,数组的存储性能比普通对象要好,在开发中我们经常使用数组来存储一些数据。

  • 数组中保存的内容我们称为元素

  • 数组使用索引(index)来操作元素

  • 索引指由0开始的整数

  • 数组的操作:

    • 创建数组(尽量不要创建非连续的数组)

    • var arr = new Array();

    • var arr = [];

    使用构造函数创建数组时,也可以同时添加元素,将要添加的元素作为构造函数的参数传递,元素之间使用隔开

    例:

    var arr2 = new Array(1,2,3);

  • 使用typeof检查一个数组时,会返回object

  • 向数组中添加元素

    • 语法:

      数组对象[索引] = 值;

    • 例子:

      arr[0] = 123;

      arr[1] = "hello";

  • 读取数组中的元素

    • 语法:

      数组 [索引];

      如果读取不存在的索引,不会报错而是会返回undefined

  • 使用字面量来创建数组,使用字面量创建数组时,可以在创建时直接添加元素

    • 语法:

      var arr = [元素1,元素2....元素N];

    • 例子:

      var arr = [123,"hello",true,null];

    • 当使用字面量创建数组时,只传递一个整数时,表示该数组的第一位索引值为这个整数。但是当使用构造函数创建数组时,只传递一个整数,表示该数组的长度为这个整数。

  • 数组中的元素可以是任意的数据类型,也可以是对象,也可以是函数,也可以放数组

  • 获取和修改数组的长度

    • 使用length属性来操作数组的长度

    • 获取长度:

      数组.length

    • length获取到的是数组的最大索引+1

    • 对于连续的数组,length获取到的就是数组中元素的个数

  • 修改数组的长度

    • 数组.length = 新长度

    • 如果修改后的length大于原长度,则多出的部分会空出来

    • 如果修改后的length小于原长度,则原数组中多出的元素会被删除

  • 向数组的最后添加元素

    • 数组[数组.length] = 值;
  • 数组的方法

    • push()

      • 用来向数组的末尾添加一个或多个元素,并返回数组新的长度

        可以将要添加的元素作为方法的参数传递

      • 语法:数组.push(元素1,元素2,元素N)

    • pop()

      • 用来删除数组的最后一个元素,并返回被删除的元素
    • unshift()

      • 向数组的前边添加一个或多个元素,并返回数组的新的长度

      • 向前边插入元素以后,其他的元素索引会依次调整

    • shift()

      • 删除数组的前边的一个元素,并返回被删除的元素
    • slice()

      • 可以从一个数组中截取指定的元素

      • 该方法不会影响原数组,而是将截取到的内容封装为一个新的数组并返回

      • 参数:

        1. 截取开始位置的索引(包括开始位置)

        2. 截取结束位置的索引(不包括结束位置)

        • 第二个参数可以省略不写,如果不写则一直截取到最后

        • 参数可以传递一个负值,如果是负值,则从后往前数

    • splice()

      • 可以用来删除数组中指定元素,并使用新的元素替换,也可以替换元素,也可以在指定位置添加元素,该方法会将删除的元素封装到新数组中返回

      • 参数:

        1. 删除开始位置的索引

        2. 删除的个数

        3. 三个以后,都是替换的元素,这些元素将会插入到开始位置索引的前边

    • reverse()

      • 可以用来反转一个数组,它会对原数组产生影响
    • concat()

      • 可以连接两个或多个数组,它不会影响原数组,而是新数组作为返回值返回

      • 不仅可以传数组,还可以传元素

    • join()

      • 可以将一个数组转换为一个字符串,它不会影响原数组,而是将转换后的字符串作为返回值返回

      • 参数:

        需要一个字符串作为参数,这个字符串将会作为连接符来连接数组中的元素

        如果不指定连接符则默认使用,

    • sort()

      • 可以对一个数组中的内容进行排序,默认是按照Unicode编码进行排序,调用以后,会直接修改原数组。

      • 即使对于纯数字的数组,使用sort()排序时,也会按照Unicode编码进行排序,所以对数字进行排序时,可能会得到错误的结果。

      • 可以自己指定排序的规则,需要一个回调函数作为参数:

        使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边

        浏览器会根据回调函数的返回值来决定元素的顺序,

        如果返回一个大于0的值,则元素会交换位置

        如果返回一个小于0的值,则元素位置不变

        如果返回一个0,则认为两个元素相等,也不交 换位置

        function(a,b){
        
        //升序排列
        
        //return a-b;
        
        //降序排列
        
        return b-a;
        
        }
        
  • 遍历数组

    • 遍历数组就是将数组中元素都获取到

    • 一般情况我们都是使用for循环来遍历数组:

      for(var i=0 ; i<数组.length ; i++){
      
      //数组[i]
      
      }
      
  • 使用forEach()方法来遍历数组(不兼容IE8)

      ```
      数组.forEach(function(value , index , obj){
    
      });
      ```
    

    forEach()方法需要一个回调函数作为参数,

    由我们创建但是不由我们调用的函数,我们称为回调函数

    数组中有几个元素,回调函数就会被调用几次,每次调用时,都会将遍历到的信息以实参的形式传递进来,我们可以定义形参来获取这些信息。

    浏览器会在回调函数中传递三个参数

      value:正在遍历的元素
    
      index:正在遍历元素的索引
      
      obj:正在被遍历的对象
    

函数

  • call()

    call()方法可以将实参在对象之后依次传递。

  • apply()

    • 这两个方法都是函数对象的方法需要通过函数对象来调用

    • 通过两个方法可以直接调用函数,并且可以通过第一个实参来指定函数中this

    • 不同的是call是直接传递函数的实参而apply需要将实参封装到一个数组中传递。

  • arguments

    • 在调用函数时,浏览器每次都会传递进两个隐含的参数:

      1. 函数的上下文对象this

      2. 封装实参的对象arguments

    • arguments是一个类数组元素,可以通过索引来操作数据,也可以获取长度,它用来封装函数执行过程中的实参

    • arguments.length可以用来获取实参的长度,所以即使不定义形参,也可以通过arguments来使用实参

    • arguments中有一个属性callee表示当前执行的函数对象

  • this

    • this是函数的上下文对象,根据函数的调用方式不同会指向不同的对象

      1. 以函数的形式调用时,this是window

      2. 以方法的形式调用时,this是调用方法的对象

      3. 以构造函数的形式调用时,this是新构造的那个对象

      4. 使用call和apply调用时,this是指定的那个对象

      5. 在全局作用域中this代表window

Date对象

  • 在js中使用Date对象表示一个时间

  • 如果直接使用构造函数创建一个Date对象,则会封装为当前代码执行的时间。

  • 创建一个指定的时间对象,需要在构造函数中传递一个表示时间的字符串作为参数

  • 日期的格式 月份/日/年 时:分:秒

  • getDate()获取当前日期对象是几日

  • getDay()获取当前日期对象是周几,0表示周日,1表示周一

  • getMouth()获取当前日期对象的月份,会返回一个0-11的值,0表示1月

  • getFullyear()获取当前日期对象以四位数字返回年份

  • getTime()获取当前日期对象的时间戳,时间戳指的是从格林威治标准时间的1970年1月1日,0分0秒,到当前日期所花费的毫秒数(1秒=1000毫秒)计算机底层在保存时间时使用都是时间戳。

  • Date.now()获取当前的时间戳

\

Math

  • Math和其他的对象不同,他不是一个构造函数

  • 它属于一个工具类不用创建对象,它里边封装了数学运算相关的属性和方法

  • Math.abs()可以计算一个数的绝对值

  • Math.ceil()可以对一个数进行向上取整,小数位只要有值就自动进1

  • Math.floor()可以对一个数进行向下取整,小数部分会被舍掉

  • Math.round()可以对一个数进行四舍五入取整

  • Math.random()可以用来生成一个0-1之间的随机数

  • Math.max()可以获取多个值中的最大值

  • Math.min()可以获取多个值中的最小值

  • Math.pow(x,y)返回x的y次幂

  • 生成一个0-x之间的随机数

    Math.round(Math.random()*x)

  • 生成一个x-y之间的随机数

    Math.round(Math.random()*(y-x)+x)

包装类

  • 在JS中为我们提供了三个包装类:

    String() Boolean() Number()

  • 通过这三个包装类可以创建基本数据类型的对象

    例子:

    var num = new Number(2);

    可以将基本数据类型字符串转换为String对象

    var str = new String("hello");

    可以将基本数据类型的数字转换为Number对象

    var bool = new Boolean(true);

    可以将基本数据类型的布尔值转换为Boolean对象

  • 但是在实际应用中千万不要这么干。如果使用基本数据类型的对象,在做一些比较时可能会带来一些不可预期的结果

  • 当我们去操作一个基本数据类型的属性和方法时,解析器会临时将其转换为对应的包装类,然后再去操作属性和方法,操作完成以后再将这个临时对象进行销毁。

字符串的相关的方法

  • 字符串在底层是以字符数组的形式保存的

    length

    • 获取字符串的长度

    charAt()

    • 根据索引获取指定的字符

    charCodeAt()

    • 根据索引获取指定的字符编码

    String.fromCharCode()

    • 根据字符编码获取字符

    concat()

    • 可以用来连接两个或多个字符串

    indexOf()

    lastIndexOf()

    • 从一个字符串中检索指定内容

    • 需要一个字符串作为参数,这个字符串就是要检索的内容,

      如果找到该内容,则会返回其第一次出现的索引,如果没有找到则返回-1。

    • 可以指定一个第二个参数,来表示开始查找的位置

    • indexOf()是从前向后找

    • lastIndexOf()是从后向前找

    slice()

    • 可以从一个字符串中截取指定的内容,并将截取到内容返回,不会影响原变量

    • 参数:

      第一个:截取开始的位置(包括开始)

      第二个:截取结束的位置(不包括结束)

    • 可以省略第二个参数,如果省略则一直截取到最后

    • 可以传负数,如果是负数则从后往前数

    substr()

    • 和slice()基本一致,不同的是它第二个参数不是索引,而是截取的数量

    substring()

    • 和slice()基本一致,不同的是它不能接受负值作为参数,如果设置一个负值,则会自动修正为0,

    • substring()中如果第二个参数小于第一个,自动调整位置

    toLowerCase()

    • 将字符串转换为小写并返回

    toUpperCase()

    • 将字符串转换为大写并返回

    split()

    • 可以根据指定内容将一个字符串拆分为一个数组,这个方法即使不全局匹配也会全部拆分

    • 如果传递一个空串参数,则每个字符串都会变成数组中的元素

    • 参数:

    • 需要一个字符串作为参数,将会根据字符串去拆分数组

    • 可以接收一个正则表达式,此时会根据正则表达式去拆分数组

    match()

    • 可以将字符串中和正则表达式匹配的内容提取出来

    • 默认情况下match()只会找到第一个符合要求的内容,找到以后就停止检索

      可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容

    • 参数:

    • 正则表达式,可以根据该正则表达式将字符串中符合要求的内容提取出来,并且封装到一个数组中返回

    replace()

    • 可以将字符串中指定内容替换为新的内容

    • 参数:

    • 第一个:被替换的内容,可以是一个正则表达式

    • 第二个:替换的新内容

    search()

    • 可以搜索字符串中是否有指定内容

      search()只会查找第一个,及时设置全局匹配也没用

    • 如果搜索到指定内容,则会返回第一次出现的索引,如果没有搜索到返回-1

    • 可以根据正则表达式去字符串中查找指定的内容

    • 参数:

      正则表达式,将会根据该表达式查询内容,

      并且将第一个匹配到的内容的索引返回,如果没有匹配到任何内容,则返回-1。

正则表达式

  • 正则用来定义一些字符串的规则,程序可以根据这些规则来判断一个字符串是否符合规则,也可以将一个字符串中符合规则的内容提取出来。

    使用typeof检查正则对象,会返回object

  • 创建正则表达式

  • 使用构造函数的方式创建更加灵活

    var reg = new RegExp("正则","匹配模式");

  • 使用字面量的方式创建更加简单

    reg = /正则表达式/匹配模式

  • 语法:

    匹配模式:

      i:忽略大小写
    
      g:全局匹配模式
    
  • 设置匹配模式时,可以都不设置,也可以设置1个,也可以全设置,设置时没有顺序要求

正则语法

| 或

[][^ ] 除了

[a-z] 小写字母

[A-Z] 大写字母

[A-z] 任意字母

[0-9] 任意数字

正则表达式

  • 语法:

  • 量词

    通过量词可以设置一个内容出现的次数

    量词只对它前边的一个内容起作用

    {n} 正好n次

    {m,n} m-n次

    {m,} 至少m次

    + 至少1次 {1,}

    ? 0次或1次 {0,1}

    * 0次或多次 {0,}

  • 转义字符

    \ 在正则表达式中使用\作为转义字符

    \. 表示.

    \\ 表示\

    . 表示任意字符

    \w表示任意字母,数字,下划线

    • 相当于[A-z0-9_]

    \W除了字母,数字,下划线

    • 相当于[^A-z0-9_]

    \d

    • 任意数字[0-9]

    \D

    • 除了数字[^0-9]

    \s

    • 空格

    \S

    • 除了空格

    \b

    • 单词边界

    \B

    • 除了单词边界

    ^ 表示开始

    $ 表示结束

  • 方法:

    test()

    • 可以用来检查一个字符串是否符合正则表达式

    • 如果符合返回true,否则返回false

    注意:使用构造函数时,由于它的参数是一个字符串,而\是字符串中转义字符,如果要使用\则需要使用\\来代替。

  • 正则表达式举例:

    1. 开头或者结尾是a / ^a | a$/

    2. 正则表达式表示手机号

    手机号的规则:

      1. 以1开头 
      2. 第二位3-9任意数字 
      3. 三位以后任意数字9个
    

    正则:/^1[3-9][0-9]{9}$/

    1. 去除字符串中前后的空格

      / ^\s* |\s*$/g

    2. 正则表达式表示电子邮件

    任意字母数字下划线 .任意字母数字下划线@ 任意字母数字 .任意字母(2-5位)

    /^\w{3,} (\.\w+)* @ [A-z0-9]+ (\.[A-z]{2,5}){1,2}$/

js中的DOM

DOM,Document Object Model文档对象模型,dom的作用是通过js操作网页的

  • 文档:表示的是整个HTML网页文档

  • 对象:表示将网页中的每一个部分都转换为了一个对象。

  • 模型:使用模型来表示对象之间的关系,这样方便我们获取对象。

  • 节点:Node,是构成网页的最基本的组成部分,网页中的每一个部分都是一个节点。

常用节点分为四类:

  • 文档节点:整个HTML文档

  • 元素节点:HTML文档中的HTML标签

  • 属性节点:元素的属性

  • 文本节点: HTML标签中的文本内容

浏览器已经为我们提供文档节点对象这个对象是window属性,可以在页面中直接使用,文档节点代表的是整个网页。

  • 通过id属性获取一个元素节点对象

    document.getElementById();

  • 通过标签名获取一组元素节点对象

    getElementsByTagName();

    这个方法会给我们返回一个类数组对象,所有查询到的元素都会封装到对象中。即使查询到的元素只有一个,也会封装到数组中返回。

  • 通过name属性获取一组元素节点对象

    getElementsByName()

  • 对象名.innerHTML 通过这个属性可以获取到元素内部的HTML代码,对于自结束标签,这个属性没有意义。

  • innerText该属性可以获取到元素内部的文本内容, 它和innerHTML类似,不同的是它会自动将html去除

  • 如果需要读取元素节点属性,直接使用元素.属性名。注意:class属性不能采用这种方式。读取class属性时需要使用元素.className

js中的事件

  • 事件就是文档或浏览器窗口中发生的一些特定的交互瞬间。jsHTML之间的交互是通过事件实现的。

  • 处理事件的方式

    • 可以在事件对应的属性中设置一些js代码,这样当事件被触发时,这些代码将会执行。这种写法称为结构和行为耦合,不方便维护,不推荐使用。

    • 可以为按钮的对应事件绑定处理函数的形式来响应事件。这样当事件被触发时,其对应的函数将会被调用。

    元素名.事件 = function(){}

  • 例如,为id为btn的button绑定一个单击事件

        btn.onclick = function(){

        alert("I'm button");

        };

像这种为单击事件绑定的函数,称为单机响应函数。

  • 浏览器在加载一个页面时,是按照自上向下的顺序加载的,读取到一行就运行一行,如果将script标签写到页面的上边,在代码执行时,页面还没有加载,DOM对象也没有加载,会导致无法获取到DOM对象。

  • onload事件会在整个页面加载完成之后被触发,为window绑定一个onload事件,该事件对应的响应函数将会在页面加载完成之后执行,这样可以确保我们的代码执行时所有的DOM对象已经加载完毕了。

    window.onload=function(){ };

js中DOM查询

  • 获取元素节点的子节点

  • 通过具体的元素节点调用

    1. getElementsByTagName()

    • 方法,返回当前节点的指定标签名后代节点

    1. childNodes

    • 属性,表示当前节点的所有子节点

    childNodes属性会获取包括文本节点在内的所有节点,根据DOM标签,标签间空白也会当成文本节点,注意:在IE8及以下的浏览器中,不会将空白文本当成子节点

    1. firstChild

    • 属性,表示当前节点的第一个子节点(包括空白文本节点)

    1. lastChild

    • 属性,表示当前节点的最后一个子节点

    1. children

    • 属性 ,可以获取当前元素的所有子元素

    1. firstElementChild

    不支持IE8及以下的浏览器,如果需要兼容他们尽量不要使用。

    • 属性 ,获取当前元素的第一个子元素
  • 获取父节点和兄弟节点

  • 通过具体的节点调用

    1. parentNode

    • 属性,表示当前节点的父节点

    1. previousSibling

    • 属性,表示当前节点的前一个兄弟节点 (也可能获取到空白的文本)

    1. nextSibling

    • 属性,表示当前节点的后一个兄弟节点

    1. previousElementSibling

    • 属性,获取前一个兄弟元素,IE8及以下不支持
  • 定义一个函数,专门用来为指定元素绑定单击响应函数

    参数:

      idstr 要绑定单击响应函数的对象的id属性值
    
      fun 事件的回调函数,当单击元素时,该函数将会被触发
    
  • 文本框的value属性值,就是文本框中填写的内容

  • 文本节点的内容是文本的Nodevalue

  • 在事件的响应函数中,响应函数是给谁绑定的,this就是谁

  • document中有一个属性body,他保存的是body的引用

    document.body

    document.documentElement保存的是html根标签

    document.all代表的是页面中的所有元素

  • 根据元素的class属性值查询一组元素节点对象

    document.getElementsByClassName()可以根据class属性值获取一组元素节点对象,但是该方法不支持IE8及以下浏览器。

  • document.querySelector()

    • 需要一个选择器的字符串作为参数,可以根据一个css选择器来查询一个元素节点对象

    • 虽然IE8中没有getElementsByClassName(),但是可以使用querySelector()代替

    • 使用该方法总会返回唯一的一个元素,如果满足条件的元素有多个,那么它只会返回第一个。

  • document.querySelectorAll()

    • 该方法和querySelector()用法类似,不同的是它会将符合条件的元素封装到一个数组中返回

    • 即使符合条件的元素只有一个,他也会返回数组。

  • document.createElement()

    • 可以用于创建一个元素节点对象

    • 它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,并将创建好的对象作为返回值返回。

  • document.createTextNode()

    • 可以用来创建一个文本节点对象

    • 需要一个文本内容作为参数,将会根据该内容创建文本节点,并将新的节点返回。

  • appendChild()

    • 向一个父节点中添加一个新的子节点

    • 用法:父节点.appendChild(子节点);

  • insertBefore()

    • 可以在指定的子节点前插入新的子节点

    • 语法: 父节点.insertBefore(新节点,旧节点);

  • replaceChild()

    • 可以使用指定的子节点替换已有的子节点

    • 语法: 父节点.replaceChild(新节点,旧节点);

  • removeChild()

    • 可以删除一个子节点

    • 语法: 父节点.removeChild(子节点);

    子节点.parentNode.removeChild(子节点);更方便,可以不用知道子节点的父节点是谁

  • 使用innerHTML也可以完成DOM的增删改的相关操作,一般我们会两种方式结合使用。

  • 点击超链接以后,超链接会跳转页面,这个是超链接的默认行为,但是此时我们不希望出现默认行为,可以通过在响应函数的最后return false来取消默认行为。

  • confirm()用于弹出一个带有确认和取消按钮的提示框

    • 需要一个字符串作为参数,该字符串将会作为提示文字显示出来

    • 如果用户点击确认则会返回true,如果点击取消则返回false

  • for循环会在页面加载之后立即执行,而响应函数会在触发事件时才执行,当响应函数执行时,for循环早已执行完毕。

通过js修改元素的样式

  • 语法:元素.style.样式名 = 样式值

  • 注意:如果css的样式名中含有-,这种名称在js中是不合法的,例如background-color,需要将这种样式名修改为驼峰命名法,去掉-,然后将-后的字母大写。

  • 我们通过style属性设置的样式都是内联样式,而内联样式有较高的优先级,所以通过js修改的样式往往会立即显示。但是如果在样式中写了!important,则此时样式会有最高的优先级,即使通过js也不能覆盖该样式,此时将会导致js修改样式失效,所以尽量不要为样式添加!important

  • 读取元素的样式

    • 语法: 元素.style.样式名

    • 通过style属性设置和读取的都是内联样式,无法读取样式表中的样式。

  • 获取元素的当前显示的样式

    • 语法:元素.currentStyle.样式名

    • 它可以用来读取当前的元素正在显示的样式。如果当前元素没有设置样式,则获取它的默认值

    • currentStyle只有IE浏览器支持,其他的浏览器不支持

  • 在其他的浏览器中可以使用getComputedStyle()这个方法来获取元素当前的样式,这个方法是window的方法,可以直接使用

    需要两个参数

    第一个:要获取样式的元素

    第二个:可以传递一个伪元素,一般都传null

    该方法会返回一个对象,对象中封装了当前元素对应的样式

    可以通过对象.样式名来读取样式

    如果获取的样式没有设置,则会获取到真实的值,而不是默认值,比如:没有设置width,它不会获取到auto,而是一个长度。

    该方法不支持IE8及以下的浏览器。

    通过currentStylegetComputedStyle()读取到的样式都是只读的。不能修改,如果要修改必须通过style属性

  • 定义一个函数,用来获取指定元素的当前的样式

    参数:

    obj 要获取样式的元素

    name 要获取的样式名

function getStyle(obj,name){
    if(window.getComputedStyle){
        return getComputedStyle(obj,null)[name];
    }else{
        return obj.currentStyle[name];
    }
}

if判断中写window.getComputedStyle是因为,不加window,它是一个变量,需要在作用域中寻找,加了window,它变成了对象的属性,变量如果找不到会报错,而属性找不到会返回undefined

  • clientWidth,clientHeight

    • 这两个属性可以获取元素的可见宽度和高度

    • 这些属性都是不带px的,返回都是一个数字,可以直接进行计算。

    • 会获取元素宽度和高度,包括内容区和内边距。

    • 这些属性都是只读的,不能修改。

  • offsetWidth,offsetHeight

    • 获取元素的整个的宽度和高度,包括内容区,内边距和边框
  • offsetParent

    • 可以用来获取当前元素的定位父元素。

    • 会获取到离当前元素最近的开启了定位的祖先元素

    • 如果所有的祖先元素都没有开启定位,则返回body

  • offsetLeft

    • 当前元素相对于其定位父元素的水平偏移量
  • offsetTop

    • 当前元素相对于其定位父元素的垂直偏移量
  • scrollWidthscrollHeight

    • 可以获取元素整个滚动区域的宽度和高度。
  • scrollLeft

    • 可以获取水平滚动条滚动的距离
  • scrollTop

    • 可以获取垂直滚动条滚动的距离
  • 当满足scrollHeight - scrollTop == clientHeight

    说明垂直滚动条滚动到底了

  • 当满足scrollWidth - scrollLeft == clientWidth

    说明水平滚动条滚动到底了

  • 如果为表单项添加disabled="disabled",则表单项变成不可用的状态

  • onscroll

    • 该事件会在元素的滚动条滚动时触发
  • disabled属性可以设置一个元素是否禁用

    如果设置为true,则元素禁用

    如果设置为false,则元素可用

事件对象

  • 当事件的响应函数被触发时,浏览器每次都会将一个事件对象作为实参传递进响应函数,在事件对象中封装了当前时间相关的一切信息,比如,鼠标的坐标,键盘哪个按键被按下,鼠标滚轮滚动的方向

  • onmousemove

    • 该事件将会在鼠标在元素中移动时被触发
  • 在IE8中,响应函数被触发时,浏览器不会传递事件对象,在IE8及以下的浏览器中,是将事件对象作为window对象的属性保存的

  • 兼容火狐,IE时

if(!event){

    event = window.event;

}

或者

event = event || window.event;来解决事件对象的兼容性问题

  • clientX可以获取鼠标指针的水平坐标

  • clientY可以获取鼠标指针的垂直坐标

    用于获取鼠标在当前的可见窗口的坐标

  • div的偏移量是相对于整个页面的

    pageXpageY可以获取鼠标相对于当前页面的坐标,但是这两个属性在IE8中不支持,所以如果需要兼容IE8,则不要使用。

  • chorme认为浏览器的滚动条是body的,可以通过body.scrollTop来获取

  • 火狐等浏览器认为浏览器的滚动条时HTML

事件的冒泡(Bubble)

  • 所谓的冒泡指的是事件的向上传导,当后代元素上的事件被触发时,其祖先元素的相同事件也会被触发。

  • 在开发中大部分情况下冒泡都是有用的,如果不希望发生事件冒泡可以通过事件对象来取消冒泡。

  • 取消冒泡

    可以将事件对象的cancelBubble设置为true

事件的委派

  • 指将事件统一绑定给元素的共同的祖先元素,这样后代元素上的时间触发时,会一直冒泡到祖先元素,从而通过祖先元素的响应函数来处理事件。

  • 事件的委派利用了冒泡,通过委派可以减少事件绑定的次数,提高程序的性能。

    例:为每一个超链接都绑定一个单击响应函数,这种操作比较麻烦,

    而且这些操作智能为已有的超链接设置事件,而新添加的超链接必须重新绑定。

    我们希望,只绑定一次事件,即可应用到多个元素上,即使元素时后添加的

    我们可以尝试将其绑定给元素的共同的祖先元素。

target

  • eventtarget表示的触发事件的对象。

    使用对象.事件=函数 的形式绑定响应函数

    它只能同时为一个元素的一个事件绑定一个响应函数,不能绑定多个,如果绑定了多个,则后边会覆盖掉前边的

  • addEventListener()

    • 通过这个方法也可以为元素绑定响应函数

    • 参数:

      1. 事件的字符串,不要on

      2. 回调函数,当事件触发时该函数会被调用

      3. 是否在捕获阶段触发事件,需要一个布尔值,一般都传false

    使用addEventListener()可以同时为一个元素的相同事件同时绑定多个响应函数,这样当事件被触发时,响应函数将会按照函数的绑定顺序执行

    • 这个方法不支持IE8及以下的浏览器

\

  • attachEvent()

    • 在IE8中可以使用attachEvent()来绑定事件,

    • 参数

      1. 事件的字符串,要on

      2. 回调函数

    • 这个方法也可以同时为一个事件绑定多个处理函数,不同的是他是后绑定的先执行,执行顺序和addEventListener()相反

  • 定义一个函数,用来为指定元素绑定响应函数

    addEventListener()中的this,是绑定事件的对象

    attachEvent()中的this,是window

    参数:

    obj 要绑定事件的对象

    eventStr 事件的字符串(不要on)

    callback 回调函数

function bind(obj , eventStr , callback){


    if(obj.addEventListener){

        //大部分浏览器兼容的方式

        obj.addEventListener(eventStr , callback , false);

    }else{

        // this是谁由调用方式决定,callback.call(obj)

        //IE8及以下

        obj.attachEvent(“on”+eventStr ,function(){

        //在匿名函数中调用回调函数

            callback.call(obj);

        });

    }

}

事件的传播

  • 关于事件的传播网景公司和微软公司有不同的理解。

  • 微软公司认为事件应该由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,

然后再向当前元素的祖先元素上传播,也就是说事件应该在冒泡阶段执行。

  • 网景公司认为事件应该是由外向内传播的,也就是当前事件触发时,应该先触发当前元素的最外层的祖先元素的事件。然后再向内传播给后代元素。

  • W3C综合了两个公司的方案,将事件传播分成了三个阶段

    1. 捕获阶段

    • 在捕获阶段时从最外层的祖先元素,向目标元素进行事件的捕获,但是默认此时不会触发事件。

    1. 目标阶段

    • 事件捕获到目标元素,捕获结束开始在目标元素上触发事件。

    1. 冒泡阶段

    • 事件从目标元素向它的祖先元素传递,依次触发祖先元素上的事件。
  • 如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true

    一般情况下我们不会希望在捕获阶段触发事件,所以这个参数一般都是false

  • IE8及以下的浏览器中没有捕获阶段。

  • 拖拽的流程

    1. 当鼠标在被拖拽元素上按下时,开始拖拽 onmousedown

    2. 当鼠标移动式被拖拽元素跟随鼠标移动 onmousemove

    3. 当鼠标松开时,被拖拽元素固定在当前位置 onmouseup

  • 当拖拽一个网页中的内容时,浏览器会默认去搜索引擎中搜索内容,此时会导致拖拽功能的异常,这个是浏览器提供的默认行为,如果不希望这个行为,则可以通过return false来取消默认行为,但是这招对IE8不起作用

  • setCapture()

    • 只有IE支持,但是在火狐中调用时不会报错,而如果使用Chrome调用,会报错。

    • 当调用一个元素的setCapture()方法以后,这个元素将会把下一次所有的鼠标按下相关的时间捕获到自身上,取消对事件的捕获releaseCapture()

  • 滚轮的事件

    onmousewheel鼠标滚轮滚动的事件,会在滚轮滚动时触发,但是火狐不支持该属性

    在火狐中需要使用DOMMouseScroll 来绑定滚动事件

    注意该事件需要通过addEventListener()函数来绑定

  • 判断鼠标滚轮滚动的方向

    event.wheelDelta 可以获取鼠标滚轮滚动的方向,往上滚为正值,往下滚为负值

    火狐中不支持wheelDelta这个属性

    在火狐中使用event.detail来获取滚动的方向,向上滚为负值,向下滚为正值

    当滚轮滚动时,如果浏览器有滚动条,滚动条会随之滚动,这是浏览器的默认行为,如果不希望发生,则可以取消默认行为return false

    使用addEventListener()方法绑定响应函数,取消默认行为时不能使用return false

    需要使用event来取消默认行为event.preventDefault(),但是IE8不支持event.preventDefault();如果直接调用会报错

  • 键盘事件

    onkeydown

    • 按键被按下

    • 对于onkeydown来说,如果一直按着某个按键不松手,则事件会一直触发

    • onkeydown连续触发时,第一次和第二次之间会间隔稍微长一点,其他的会非常的快,这种设计是为了防止误操作的发生。

    onkeyup

    • 按键被松开

    键盘事件一般都会绑定给一些可以获取到焦点的对象或者是document

    可以通过keyCode来获取按键的编码

    通过它可以判断那个按键被按下

    除了keyCode,事件对象中还提供了几个属性

    altKey

    ctrlKey

    shiftKey

    • 这个三个用来判断alt ctrlshift 是否被按下,如果按下则返回true,否则返回false

    在文本框中输入内容,属于onkeydown的默认行为

    如果在onkeydown中取消了默认行为,则输入的内容,不会出现在文本框中

BOM

  • 浏览器对象模型

  • BOM中为我们提供了一组对象,用来完成对浏览器的操作

  • BOM对象

    Window

    • 代表的是整个浏览器的窗口,同时window也是网页中的全局对象

    Navigetor

    • 代表的是当前浏览器的信息,通过该对象可以来识别不同的浏览器

    • 由于历史原因,Navigator对象中的大部分属性已经不能帮助我们识别浏览器了

    • 一般我们只会使用userAgent来判断浏览器的信息

    userAgent是一个字符串,这个字符串中包含有用来描述浏览器信息的内容,

    不同的浏览器会有不同的userAgent

    在IE11中已经将微软和IE相关的标识都已经去除了,所以我们基本已经不能通过userAgent来识别一个浏览器是否是IE

    • 如果通过userAgent不能判断,还可以通过一些浏览器中特有的对象,来判断浏览器的信息,比如ActiveXObject,可以通过ActiveXObject in window来判断

    Location

    • 代表的是当前浏览器的地址栏信息,通过Location 可以获取地址栏信息,或者操作浏览器跳转页面

    • 如果直接打印location,则可以获取到地址栏的信息(当前页面的完整路径)

    • 如果直接将location属性修改为一个完整的路径,或相对路径,则页面会自动跳转到该路径,并且会生成相应的历史记录

    • assign()

    用来跳转到其他的页面,作用和直接修改location一样

    • reload()

    • 用来重新加载当前页面,作用和刷新按钮一样

    • 如果在方法中传递一个true 作为参数,则会强制清空缓存刷新页面

    • replace()

    • 可以使用一个新的页面替换当前页面,调用完毕也会跳转页面,不会生成历史记录不能使用回退键回退

    • History

    • 代表浏览器的历史记录,可以通过该对象来操作浏览器的历史记录

    • 由于隐私原因,该对象不能获取到具体的历史记录,只能操作浏览器向前或向后翻页。而且该操作只在当次访问时有效。

    • length

    • 属性,可以获取到当前访问的链接数量

    • back()

    • 可以用来回退到上一个页面,作用和浏览器的回退按钮一样

    • forward()

    • 可以跳转到下一个页面,作用和浏览器的前进按钮一样

    • go()

    • 可以用来跳转到指定的页面

    他需要一个整数作为参数

    1:表示向前跳转一个页面 相当于forward()

    2:表示向前跳转两个页面

    -1:表示向后跳转一个页面

    -2:表示向后跳转两个页面

    • Screen

    • 代表的是用户屏幕的信息,通过该对象可以获取到用户的显示器的相关的信息

  • 这些BOM对象在浏览器中都是作为window对象的属性保存的。

  • 可以通过window对象来使用,也可以直接使用。

  • JS的程序的执行速度是非常非常快的,如果希望一段程序可以每间隔一段时间执行一次,可以使用定时调用

  • setInterval()

    • 定时调用

    • 可以将一个函数,每隔一段时间执行一次

    • 参数:

    1. 回调函数,该函数每隔一段时间被调用一次

    2. 每次调用间隔的时间,单位是毫秒

    • 返回值:

    返回一个number类型的数据

    这个数字用来作为定时器的唯一标识

  • clearInterval()可以用来关闭一个定时器

    • 方法中需要一个定时器的标识作为参数,这样将关闭标识对应的定时器

    • clearInterval()可以接受任意参数

    如果参数是一个有效的定时器的标识,则停止对应的定时器

    如果参数不是一个有效的标识,则什么也不做

    当把定时器放在按钮的单击响应函数中时,每点击一次按钮,就会开启一个定时器,点击多次就会开启多个定时器,这就导致图片的切换速度过快,并且我们只能关闭最后一次开启的定时器,所以在开启定时器之前,需要将当前元素上的其他定时器关闭clearInterval(timer);

  • 延时调用setTimeout(function(){},时间);

    • 延时调用一个函数不马上执行,而是隔一段时间以后再执行,而且只会执行一次

    • 延时调用和定时调用的区别,定时调用会执行多次,而延时调用只会执行一次

  • 使用clearTimeout()来关闭一个延时调用

  • 延时调用和定时调用实际上是可以相互代替的,在开发中可以根据自己需要去选择

  • 通过style属性来修改元素的样式,每修改一个样式,浏览器就需要重新渲染一次页面,这样的执行的性能是比较差的,而且这种形式当我们要修改多个样式时也不太方便。如何用一行代码,可以同时修改多个样式?

    • 可以通过修改元素的class属性来间接的修改样式,这样一来,我们只需要修改一次,即可同时修改多个样式,浏览器只需要重新渲染页面一次,性能比feedback较好,并且这种方式,可以是表现和行为进一步的分离。

JSON

  • js中的对象只有js自己认识,其他的语言都不认识

-JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别。

并且可以转换为任意语言的对象,JSON在开发中主要用来数据的交互

  • JSON

    • JavaScript Object Notation JS对象表示法

    • JSONJS对象的格式一样,只不过JSON字符串中的属性名必须加双引号

其他的和JS语法一致

JSON分类:

1. 对象 { }

2. 数组 [ ]

JSON中允许的值,

1. 字符串

2. 数值

3. 布尔值

4. null

5. 对象

6. 数组

JSON字符串转换为JS中的对象

JS中,为我们提供了一个工具类,就叫JSON

这个对象可以帮助我们将一个JSON转换为JS对象,也可以将一个JS对象转换为JSON

JSON.parse()

- 可以将`JSON`字符串转换为`js`对象

- 它需要一个`JSON`字符串作为参数,会将该字符串转换为`js`对象

JSON.stringify()

- 可以将一个`js`对象转换为`JSON`字符串

- 需要一个`js`对象作为参数,会返回一个`JSON`字符串

`JSON`这个对象在IE7及以下的浏览器中不支持,所以在这些浏览器中调用时会报错

eval()

- 这个函数可以用来执行一段字符串形式的js代码,并将执行结果返回

- 如果使用`eval()`执行的字符串中含有{ },它会将{ }当成是代码块

如果不希望将其当成代码块解析,则需要在字符串前后各加一个()

- 这个函数的功能很强大,可以直接执行一个字符串中的js代码,但是在开发中尽量不要使用,首先是它的执行性能比较差,然后它还具有安全隐患。

如果需要兼容IE7及以下的JSON操作,则可以通过引入一个外部的js文件来处理