[TOC]

一、JavaScript 笔记

JavaScript负责页面中的的行为。
它是一门运行在浏览器端的脚本语言。

1. JS的编写的位置

  1. 可以编写到标签的指定属性中
  • onclick只有鼠标点击的时候才生效;

<button onclick="alert('hello');">我是按钮</button>

  • 也可以在超链接中使用alert,但是需要标注上javascript;将js代码写在超链接的href中,这样当点击超链接时,会执行href;

<a href="javascript:alert('aaa');">超链接</a>

<body>
<button onclick="alert('你点我干嘛!')">点击</button>
<a href="javascript:alert('让你点了么?')">也点我一下试试</a>
<body/>

QQ图片20220607174036.png

  • 虽然可以将js 写到标签中,但是属于结构和行为耦合不方便维护(不推荐)
  1. 可以编写到script标签中

<script type="text/javascript"> //编写js代码</script>

<head> 
<!--JS代码需要编写到 script得标签中-->
       <!--此处得type写不写都可-->
    <script type="text/javascript">
        /*控制浏览器 弹出第一个警告框*/
        alert("这是我运行的第一个代码");

    </script>
</head>

QQ图片20220607164330.png

  1. 也可以将代码编写到外部的js文件中,然后通过标签将其引入
  • 写在外部文件中可以在不同的页面同时引用,也可以利用到浏览器的缓存机制(推荐使用)

    浏览器的缓存机制:就是将已经访问过的资源在本地进行缓存,相同的url页面无更新,则会直接从本地调用

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

<script type="text/javascript" src="文件路径"></script>

<script type="text/javascript" src="./script.js">
</script>
  • 注意:script标签一旦引入外部文件,就不能再编写代码了,即使编码代码浏览器也会自动忽略。可以再创建一个新的script标签用于编写内部代码(相当于一个一一对应的原则,外部对一个,内部对一个); ```javascript //内部编写

//外部引入

<a name="mta2q"></a>
## 2. 输出语句

1. 警告窗口/弹窗 **alert**

`alert("要输出的内容");  `<br />该语句会在浏览器窗口中弹出一个警告框

2. 页面内输出内容 **document**

`document.write("要输出的内容");  `<br />一个网页html 就是一个文档 == 显示效果相当于在body中输出一个内容<br />该内容将会被写到body标签中,并在页面中显示

3. 控制台 **console**

`console.log("要输出的内容");  `<br />该内容会被写到开发者工具的网页控制台中(只有开发者可见)
<a name="uX5E7"></a>
## 3. 基本的语法

1. 每条语句需要加分号
-  js函数声明不需要分号;  但是赋值语句要加分号;
-  可以用逗号 ,同时声明并赋值;
-   可以使用{ } 来为语句分组,要么都执行,要么都不执行;一个{}也称为一个代码块;
```javascript
function functionName(arg0,arg1,arg2){  
//函数声明  
}  
var functionName=function(arg0,arg1,arg2){  
//函数表达式  
};(注意分号)  

// 可以用逗号 ,同时声明并赋值;
var a=1, b=2, c=3;

//js中的代码块只有分组的作用,且在代码块中的内容在{}外仍然可见
{
  var a = 10;
  alert("hello");
  console.log("你好");
  document.write("语句");
}
console.log("a ="+a);
  1. 注释
  • 单行注释 //注释内容
  • 多行注释 / 注释内容 /
  1. JS严格区分大小写
  • JS中每条语句以分号(;)结尾如果不写分号,浏览器会自动添加,但是会消耗一些系统资源, 而且有些时候,浏览器会加错分号,所以在开发中分号必须写;
  1. JS中会自动忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化。

    4. 字面量和变量

    4.1 字面量(常量)

  • 就是一些固定的值,比如 1 2 3 4 true false null NaN “hello”
  • 字面量都是不可以改变的,可以直接使用
  • 由于字面量不是很方便使用,所以在JS中很少直接使用字面量

    4.2 变量 var

  • 变量可以用来保存字面量,并且可以保存任意的字面量

  • 一般都是通过变量来使用字面量,而不直接使用字面量,而且也可以通过变量来对字面量进行一个描述
  • 声明变量

      使用`**var**`关键字来声明一个变量,<br />          eg: 先声明后赋值 `**var** a;  a = 1; `<br />                 声明且同时赋值` **var** a = 456; `  
    

    4.3 标识符

  • 在JS中所有的可以自主命名的内容,都可以认为是一个标识符, 是标识符就应该遵守标识符的规范。

  • 比如:变量名、函数名、属性名
  • 规范:
    1.标识符中可以含有字母、数字、_、$
    • 2.标识符不能以数字开头
      3.标识符不能是JS中的关键字和保留字
    • QQ图片20220607224258.jpg
      4.标识符一般采用驼峰命名法

二、数据类型

1. 六种数据类型(2+3+1)

JS中一共分成六种数据类型 5个基本数据类型+object
String 字符串
Number 数值
Boolean 布尔值
Null 空值
Undefined 未定义
Object 对象
其中基本数据类型有 5个
typeof运算符检查数据类型

1.String 字符串

  • JS中的字符串需要使用引号引起来, 双或单引号都行 ;
  • 相同类型的引号不能嵌套,但是双引号可以嵌套单引号,单引号可以嵌套双引号;
  • 需求强制使用引号,可以使用在字符串中使用\作为转义字符
    • \’ ==> ‘
    • \” ==> “
    • \n ==> 换行
    • \t ==> 制表符
    • \ ==> \
  • 使用typeof运算符检查字符串时,会返回”string”

     <script>
          var str = "hello"
          /*函数里 就可以用自变量,也可以用字符串(常量)*/ 
          console.log(str);
          console.log("hello");
    
          var strr ;
          /*相同类型的引号不能嵌套,不同类型引号可以嵌套*/
          strr = "我说:'今天天气真不错!'";
          document.write(strr);
      </script>
    

    2.Number 数值

    JS中所有的整数和浮点数都是Number类型

  • 最大能表示的值:Number.MAX_VALUE= 1.7976931348623157e+308

    `console.log(Number.MAX_VALUE);`
    
  • 超过最大值的数用 infinity表示,返回结果也是 number;
    Infinity 正无穷 , -Infinity 负无穷

      特殊的用 ` a = infinity ;`表示正无穷;
    
     //最大值 infinity
          a = Number.MAX_VALUE * Number.MAX_VALUE ;
          document.write(a);
    
          a = infinity ;
    
      NaN 非法数字(Not A Number)
    
  • 其他进制的数字的表示:
    0b 开头表示二进制,但是不是所有的浏览器都支持
    0 开头表示八进制
    0x 开头表示十六进制

  • 使用 typeof 检查一个Number类型的数据时,会返回”number”
    (包括NaN 和 Infinity)
  • 不要用JS进行对精确度要求比较高的运算(例如涉及到钱)

         //number
          //数字123
          var a = 123;
          //字符串123
          var b = "123";
          //可以通过 typeof 来检查类型
          console.log(typeof a);
          document.write(typeof b);
    

    3.Boolean 布尔值

  • 布尔值主要用来进行逻辑判断,布尔值只有两个
    true 逻辑的真
    false 逻辑的假
    使用typeof检查一个布尔值时,会返回”boolean”

    var bool = true;
    console.log(bool);
    console.log(typeof bool);
    

    4.Null 空值

    空值专门用来表示为空的对象,Null类型的值只有一个null
    使用typeof检查一个Null类型的值时会返回”object”

    5.Undefined 未定义

    变量 声明没赋值 就是undefined
    该类型的值只有一个 undefined
    使用typeof检查一个Undefined类型的值时,会返回”undefined”

    6. 引用数据类型

    Object 对象

    2. 类型转换

    将其他的数据类型,转换为String 、Number 或 Boolean

    2.1 转换为String

    方式一 调用.toString()方法

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

  • 不会改变原变量的值,该函数有返回值;
    var a = 123;
    a = a.toString();
    注意:这个方法不适用于null和undefined
    由于这两个类型的数据中没有方法,所以调用toString()时会报错

    方式二 调用 String()函数

  • 调用String()函数(强制类型转换),把被转换的数据作为参数传递给参数

  • **var** a = 123;

     ` a = String(a);`  
    
  • 对于Number Boolean String与toString()方法效果一致; 而对于null值,直接转换为字符串”null”,前者是字面量,后者是字符串;对于undefined直接转换为字符串”undefined”;所以String()函数的适应性更广;

    方式三 +””(隐式的类型转换):

  • 为任意的数据类型 +””

  • **var** a = **true**;

     ` a = a + "";  //"ture"`<br />原理:任意数据类型与字符串相加,都会转换为字符串;
    

    2.2 转换为Number

    方式一 调用Number()函数

    (强制类型转换):
    **var** s = "123";
    s = Number(s);
    转换的情况:

  1. 字符串 > 数字
    如果字符串是一个合法的数字,则直接转换为对应的数字
    如果字符串是一个非法的数字,则转换为NaN
    如果是一个空串或纯空格的字符串,则转换为0
  2. 布尔值 > 数字
    true转换为1
    false转换为0
  3. 空值 > 数字
    null转换为0
  4. 未定义 > 数字
    undefined 转换为NaN

    方式二 parseInt()或parseFloat()

  • 这两个函数专门用来对付字符串的,属于强制类型转换;
  • 如果对非String使用parseInt()或parseFloat(),它会先将其转换为String然后在操作 parseInt();因为执行这两个函数需要逐个比对;

    var s = true;//设置s为布尔类型
          s = parseInt(s);//此时 转变为了字符串类型 “ture”
          console.log(typeof s);
          console.log(s);
    
  • 可以将一个字符串中的有效的整数位提取出来,并转换为Number;

**var** a = "123.456px";
a = parseInt(a); //123
如果需要可以在parseInt()中指定一个第二个参数,来指定进制parseFloat()可以将一个字符串中的有效的小数位提取出来,并转换为Number
例子:
**var** a = "123.456px";
a = parseFloat(a); //123.456

方式三(隐式的类型转换):

使用一元的+来进行隐式的类型转换
例子:
**var** a = "123";
a = +a;
原理:和Number()函数一样

2.3 转换为布尔值

方式一 Boolean()函数(

使用Boolean()函数,属于强制类型转换;
**var** s = "false";
s = Boolean(s); //true

  • 转换的情况:
    1. 字符串 > 布尔 : 除了空串其余全是true

      2. 数值 > 布尔:除了0和NaN其余的全是true<br />        3. null、undefined > 布尔 : 都是false<br />        4. 对象 > 布尔 : 都是true
    

    方式二(隐式类型转换):

    为任意的数据类型做两次非运算,即可将其转换为布尔值
    **var** a = "hello";
    a = !!a; //true

    3.其他进制的数字的了解

    ```javascript //其他进制的数字

      //16进制数字,以0x开头
      a = 0x10;
      console.log(a);//16
    
      //8进制数字,以0开头
      a = 070;
      console.log(a);//56
    
      //像“070” 这种数字有些浏览器会被当成8进制,有些会被当成10进制
       //--> 可以在parseInt(,)函数中传递第二个参数,来指定数字的进制
       a = "070";
       console.log(a);//070
       a = parseInt(a,10);
       console.log(a); //70
    
    //二进制数字,以0b开头(有些浏览器并不支持)
    a = 0b10;
    console.log(a);//2
<a name="vc1IG"></a>
# 三、基础语法
<a name="VncoS"></a>
## 3.1 运算符
运算符也称为操作符,通过运算符可以对一个或多个值进行运算或操作
<a name="ibNtu"></a>
###  3.1.1 typeof运算符
用来检查一个变量的数据类型;<br />语法:typeof 变量<br />它会返回一个值,用于描述类型的**字符串**作为结果
```javascript
var a = 123;
var b = typeof a;//"number"
//此时b获取到的是 经运算右侧等式得到的字符串

console.log(typeof b);//"string"

3.1.2 算数运算符 +、-、*、/

  • + 两值加,可以对字符串进行拼串操作;
    • 除了加法以外,对非Number类型的值进行运算时,都会先转换为Number然后在做运算 ;
    • 任何值和NaN做运算都得NaN;
    • 而做加法运算时,如果是两个字符串进行相加,则会做拼串操作,将两个字符连接为一个字符串。
    • 任何值和字符串做加法,都会先转换为字符串,然后再拼串;可以利用这一特点,将任意一个字符串转换为String,只需要将任意数据类型+”” ; ```javascript var c = 123; c = c + “” ; console.log(typeof c);//“String” console.log(c);// “123” console.log(“c = “ + c );// “c = 123”

//注意运算的顺序,加法中遇见字符串变成字符串 result = 1 + 2 + “3”;//33 result = “1” + 2 + 3;//123


- **  - **两值减,任何值做减法 运算时都会自动转换为Number;
-    可以利用这一特点做隐式数字转换;可以通过值 -0、*1、/1 将其转换为Number;
```javascript
var d = "123";
d = d - 0;// 数字123
  • * 对两个值进行乘法运算并返回结果
  • / 对两个值进行除法运算并返回结果
  • % 对两个值进行取余运算并返回结果

3.1.3 一元运算符 ++、—、+

一元运算符只需要一个操作数

一元的+ : 就是正号

var a = true; a = +a;  // a

//中间的 +2 前的加号,将字符串"2"变成数字2
var result = 1 +  +"2"  +3;//6

一元的 - : 就是负号

可以对一个数字进行符号位取反;还可以将一个非Number值先转换为Number;
**var** a = 10; a = -a; // a = -10

自增 ++(自减 —同理)

a++;// 原变量的值自增1();
++a;// 变量的新值(自增后的值);

var d = 20;
var result = d++  +  ++d  + d;//20 + 22 + 22 = 64 

d = 20;
d = d++;//d = 20

相同的是++a 还是 a++都会立即使原变量自增1; // a=2
不同的是++a和a++整体表达式的值是不同的;// 前者为2,后者为1(等式右边先赋值给等式左边,再自增);本质上就是理解自左到右的运算顺序;
//实在不行就分开理解, 对于d++ 这种: 需要取表达式的值的时候就是 看d的位置, 取d本身的值无须考虑前后都是自增1;

var n1 = 10, n2 = 20;
var n = n1++;//n=10,n1=11;
console.log('n='+n);//n=10
console.log('n1='+n1);//n1=11;

n=++n1;
console.log('n='+n);// 12
console.log('n1='+n1);//12;

n=n2--;
console.log('n='+n);//n=20
console.log('n2='+n2);//n2=19;

n= --n2;
console.log('n='+n);//n=18
console.log('n2='+n2);//n2=18;

3.1.4 逻辑运算符 && 、||、!

! 非
非运算可以对一个布尔值进行取反,true变false false边true
当对非布尔值使用!时,会先将其转换为布尔值然后再取反(两次取反可将其他的数据类型转换为布尔值)
&& 与 、 || 或

  • &&、|| 可以对符号两侧的值进行与运算
  • 一false为false,&& 两true为true; || 一true为true,两alse才false;
  • 与是一个短路的‘与’,如果第一个值是false,则不再检查第二个值 ture&&alert("是否判断了第二个"); ( || 同理 )
  • 对于非布尔值,它会将其转换为布尔值然后做运算,并返回原值 ```javascript //非布尔值首先转换成布尔值,true && true —>ture 返回原值结果2 var result = 1 && 2 ;
    consle.log(“result=”+result) ; // 2

result = “” || “hello” ; console.log(“result=”+result);//hello


- 例&& 规则:<br />1.如果第一个值为false,则返回第一个值<br />2.如果第一个值为true,则返回第二个值
<a name="LDBy3"></a>
### 3.1.5 赋值运算符 =、+=

-    = : 可以将符号右侧的值赋值给左侧变量
-  += : `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 `
<a name="LZi3M"></a>
### 3.1.6 关系运算符 > <

- 关系运算符用来比较两个值之间的大小关系的<br />`     >          >=            <            <=      `
- 如果关系成立则返回true,关系不成立则返回false。`console.log(5 > 10) // false`
- 如果比较的两个值是非数值,会将其转换为Number然后再比较。
```javascript
console.log(1 > true);// 1>1 返回false
console.log(1 >= true);// 1>=1 返回ture
console.log(1 > "0");// 1>0 返回ture
console.log(10 > null);// 10 > 0 返回true

//任何值和NaN做比较都是false
console.log(10 > "hello");//false
  • 如果比较的两个值都是字符串,此时会比较字符串的Unicode编码,而不会转换为Number。 ```javascript //比较字符串的时候是按位进行比较的 console.log(“bbc” < “b”);//第一位b与b比较一样,再比较下一个位前边的大,返回false console.log(“abc” < “b”);// a “我”);//根据 unicode 返回ture;但是比较中文没有意义;

console.log(“125556853” < “5”);//字符串只比较第一位 1<5 返回ture //所以在比较两个 字符串型的数字时,一定要转型 console.log(“125556853” < +”5”);//false

<a name="xMJBW"></a>
### 3.1.7 相等运算符==、!= 、===

1. **==** 相等,判断左右两个值是否相等,如果相等返回true,如果不等返回false<br />不相等会自动对两个值进行**类型转换**,再返回ture or flase;
```javascript
//不同的类型先转换,1 == 1
console.log("1" == 1);//ture 

//注意此处是 boolen和字符串都转换成了Number 1
console.log(ture == "1")//ture
//小细节,boolen类型的ture变成

//特殊的,此处的number没有转换成0
console.log(null == 0);//false
  1. != 不等,判断左右两个值是否不等,如果不等则返回true,如果相等则返回false
    不等也会做自动的类型转换(同相等)。
  2. === 全等,判断左右两个值是否全等,它和相等类似,只不过它不会进行自动的类型转换
    如果两个值的类型不同,则直接返回false ;
    • ==相等 和 ===全等的理解区别,前者是意义上的相等判断,后者是完全的相同;
  3. !== 不全等,和不等类似,但是它不会进行自动的类型转换,如果两个值的类型不同,它会直接返回true
  4. 特殊的值:null和undefined、NaN
    //undefined 衍生自null,所以这两个值做相等判断的时候,会返回ture
    console.log(null == undefined);//ture
    //但是 null === undefined 会返回false
    
    //Na不和任何值相等,包括他本身
    console.log(NaN == NaN);//false
    //所以 判断一个变量是否是NaN 用isNaN()函数,如果是NaN则返回ture
    var b = NaN;
    console.log(isnNaN(b));//ture
    

    3.1.8 三元运算符:?:

    语法:**条件表达式?语句1:语句2;** ```javascript var a = 10; var b = 20; var c = 50; a > b ? alert(“a大”) :alert(“b大”);// b大

var max = a > b ? a : b ; console.log(“max =”+max);//max = 20

//三者的判断 var max = a>b ? (a>c?a:c):(b>c?b:c);//max = 50


- 执行流程:<br />先对条件表达式求值判断; 如果判断结果true,执行语句1; 判断结果false,执行语句2 ;
- 若条件判断的类型不同,先转换类型
- 优先级:<br />和数学中一样,JS中的运算符也是具有优先级的,比如 先乘除 后加减 先与 后或<br />具体可以参考优先级的表格,在表格中越靠上的优先级越高,越高的越优先计算;  优先级相同的,从左往右计算。所以如果越到拿不准的,使用()来改变优先级。
<a name="hBcV4"></a>
### 3.1.9用Unicode 输出特殊符号
在控制台中,`在字符串中 使用转义字符\u  + (16进制的)四位Unicode编码 `: ` console.log("\u12620");`<br />在网页中显示,` &#编码`(注意这里的编码是10进制的):`<h1>&#2620</h1>`
```javascript
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title></title>
        <script type="text/javascript">

            /*
             * 在字符串中使用转义字符输入Unicode编码
             *  \u四位编码   这个用法只是在JS里这样写写
             * 用法如:\u0031  就表示 数字1
             * 在JS中是用\u转义,但是写在网页中的话,要用&#
             */
            console.log("\u2620");

        </script>
    </head>
    <body>

        <!--在网页中使用Unicode编码  Unicode编码的数字都是16进制的
         这里的编码需要的是10进制,所以,如果需要用到的话,需要把Unicode编码的16进制数转成10进制,再加上&#这个符号才能正确显示,例如:2620是Unicode编码的,他是16进制的,转换成10进制是9760,再在前面加上&#符号,就能正确的在网页中显示出这个Unicode编码2620的原意---一个骷髅图案
        -->
        <h1 style="font-size: 200px;">&#9760;</h1>
        <h1 style="font-size: 200px;">&#9856;</h1>

    </body>
</html>

3.2 流程控制语句

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

3.2.1 条件分支语句

  • 条件判断语句也称为 if 语句
    • if(条件表达式){ 语句… }
    • if(条件表达式){ 语句… }else{ 语句… }
    • if(条件表达式){ 语句… }else if(条件表达式){ 语句… }else if(条件表达式){ 语句… }else if(条件表达式){ 语句… }else{ 语句… }
  • 条件分 switch 语句

switch(条件表达式){
case 表达式: 语句… break;
case 表达式: 语句… break;
default: 语句… break; }

3.2.2 循环语句

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

  1. while(条件表达式){ 语句… }
  2. do{ 语句… }while(条件表达式)

两者的区别:
while:先判断后执行
do…while: 先执行后判断
do…while可以确保循环体至少执行一次。

  1. for(①初始化表达式 ; ②条件表达式 ; ④更新表达式){ ③语句… }
  2. 死循环 while(true){ } for(;;){ }

    //打印100-1000 的水仙花数
       for(var i=100; i<1000; i++)
       {
           //var bai =  i/100;//js中 不能用/直接做取整操作,需要借助取整函数;
           var bai = parseInt(i/100) ;
          // document.write(bai+"<br>");
           var shi = parseInt((i-bai*100)/10);
           var ge  = i%10;
           var flower = bai*bai*bai + shi*shi*shi + ge*ge*ge;
    
           if( i == flower)
               document.write(i+"<br>");
    
       }
    

    3.2.3 prompt()函数

    可以弹出一个带 输入文本提示框,输入一段字符串作为参数并作为提示框的提示文字;
    在弹出的提示框上 输入的内容作为函数的返回值,一般定义一个变量来接收该内容;
    var score = prompt("请输入小明的期末成绩");
    alert("score");

    四、对象(Object)

    对象是JS中的引用数据类型,对象是一种复合数据类型,在对象中可以保存多个不同数据类型的属性(好像c++中的结构体一样),使用typeof检查一个对象时,会返回object

    4.1 对象的分类:

    1.内建对象
    - 由ES标准中定义的对象,在任何的ES的实现中都可以使用
    - 比如:Math String Number Boolean Function Object….
    2.宿主对象
    - 由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
    - 比如 BOM DOM
    3.自定义对象
    - 由开发人员自己创建的对象
    拓:JS的三大组成(ES DOM BOM)https://blog.csdn.net/wwwwwww31311/article/details/113841496

  • 创建对象(相当于一个容器)

     使用new关键字调用的函数,是构造函数constructor 专门用来创建对象的函数;
    
    • 方式一:var obj = new Object();
    • 方式二:var obj = {}; //使用对象字面量创建属性
      • 使用对象字面量,在创建对象时直接向对象中添加属性
        语法:**var** obj = { 属性名:"属性值", 属性名:"属性值", 属性名:"属性值" };
        var obj = {};
        var obj2 = { 
        name:"猪八戒", 
        age:"26", 
        gender:"man",
        text:{name:"沙和尚"}
        };
        console.log(obj2.text);//沙和尚
        
  • 向对象中添加属性

    • 语法:对象.属性名 = 属性值; obj.name=”孙悟空”;
      对象["属性名"] = 属性值; //这种方式能够使用特殊的属性名 obj[“123”]=789 ;
    • 对象的属性名没有任何要求,不需要遵守标识符的规范,但是在开发中,尽量按照标识符的要求去写。
  • 读取对象中的属性
    语法:对象.属性名 obj.name
    对象[“属性名”] //“属性名”可以使字符串常量,也可以是字符串变量
    如果读取一个对象中没有的属性,它不会报错,而是返回一个undefined
  • 删除对象中的属性
    语法:delete 对象.属性名 delete 对象[“属性名”]
  • 属性值

      js**对象的属性值可以是任意数据类型**,比如是一个对象(袋子里套袋子)
    

    ```javascript var obj = new object(); var boj2 = new object(); obj2.name = “猪八戒”; //可以是任意值 obj.text = ture; obj.text = null; obj.text = undefine;

//对象的属性值也可也以是对象; obj.text = obj2; console.log(obj.text.name);//猪八戒

//对象的属性值是 函数 obj.sayname = function(){ console.log(“obj2.name”); } sayname();//猪八戒

<a name="zH4jo"></a>
## 4.2 遍历

- **使用in检查对象中是否含有指定属性**<br />语法:`"属性名" in 对象,`如果在对象中含有该属性,则返回true,如果没有则返回false;

                    循环遍历对象自身的和继承的可枚举属性(不含Symbol属性).  
```javascript
var obj  = new object();
obj.text = "猪八戒";
console.log("text2" in obj);//false
console.log("text" in obj);//ture

var obj = {'0':'a','1':'b','2':'c'};      
for(var i in obj) {   console.log(i,":",obj[i]);   }
  • 基本数据类型(变量在栈内的值 是直接保存的值)
    • String Number Boolean Null Undefined
    • 变量与变量之间是互相独立的,修改一个变量不会影响其他的变量。
    • 变量的值可以相等 ,基本数据类型比较的是值;
  • 引用数据类型 (栈内的值 是保存的变量的地址)

    • Object 对象是保存在堆内的;
    • 如果多个变量指向的是同一个对象,此时修改一个变量的属性,会影响其他的变量。
    • 比较两个变量时,对于基本数据类型,比较的就是值;对于引用数据类型比较的是地址,地址相同才相同;两个对象即使属性完全一样,也是两个不同的个体 ;

            `console.log(obj1==obj2);//false;`
      
    • 微信图片_20220613225828.jpg微信图片_20220613231239.jpg

      4.3 函数(Function)

      函数也是一个对象,也具有普通对象的功能(能有属性)
      函数中可以封装一些代码,在需要的时候可以去调用函数来执行这些代码

  1. 创建一个函数对象

    • 方式一(不常用):使用 new 关键字来创建函数对象

                                `var fun  = new  Function() ;`
      

      ```javascript var fun = new function(“console.log(“hello大家好”);”); //调用时,函数中封装的代码会按照顺序执行 fun();//hello大家好

//函数与普通对象一样 也可以添加属性 fun.name = “八戒”; console.log(fun.name);//八戒


   - **方式二(常用):使用函数声明 来创建一个函数对象**<br />**函数声明:**`**function**  **函数名( [形参1,形参2...形参N] ){   **`

**                                                                **`**     语句...  **`<br />**                                       **`**     }  **`
```javascript
function fun2(){
   console.log("八戒八戒傻得可爱");
   alert("hhhhhhha");
   document.write("who are u");
}
//调用
fun2();
  • 方式三(常用):使用函数表达式 来创建一个函数对象(本质上是个赋值语句)

** var** **函数名 = function( [形参1,形参2...形参N] ){ **
** 语句... **
** } ; **

//本质上就是将一个匿名函数 赋值给了一个变量
var fun3 = function(){
   console.log("我是匿名函数赋值给变量的封装函数的代码执行");
};
//调用
 fun3();
  1. 形参和实参
  • 形参:形参之间使用,逗号隔开;相当于在函数内声明了对应的变量但是并不赋值;形参会在调用时才 赋值;
  • 实参:
    • 调用函数时,可以在()传递实参,传递的实参会赋值给对应的形参;调用函数时JS解析器不会检查实参的类型和个数(不同的数据类型会先转换数据类型),可以传递任意数据类型的值。 ```javascript function sum(a,b){ console.log(a+b); }

sum(123,”hello”);//“123hello” sum(ture,false);//1


   - 如果实参的数量大于形参,多余实参将不会赋值,如果实参的数量小于形参,则没有对应实参的形参将会赋值undefined;
   - 实参可以是任意的数据类型,也可以是一个对象(当我们参数过多时,可以将众多参数封装到一个对象中,然后通过对象传递);还可以是一个函数;
```javascript
function fun2(o){
   console.log("我是"+o.name+",今年我"+o.age+"岁了,我是一个"+o.gender+"人,我住在+"o.address);
}

//创建一个对象,含有多个属性
var obj = {      
   name = "老祝";
   age = 26;
   gender = "男";
   address = "花果山"
};

fun2(obj);//传入对象作为实参
function sayhello(o){
   console.log("我是"+o.name+",今年我"+o.age+"岁了,我是一个"+o.gender+"人,我住在+"o.address);
}

var obj = {      
   name = "老祝";
   age = 26;
   gender = "男";
   address = "花果山"

};

sayhello(obj);



//实参也可以是 函数
function fun(a){
     //console.log("a = "+a);
     a(obj);//这里的形参a 相当于一个函数,可以调用参数obj;相当于运行sayhello(),调用参数obj;
}
fun(sayhello);//实参是函数




//传递匿名函数 作为参数
fun( funcion(){alert("hello")}  );


//区别 参数是 调用函数 和 函数对象
fun( sayhello(o) );//参数是  调用函数,相当于使用的是函数的返回值结果
fun( sayhello );   //参数是  函数对象,相当于直接使用函数
  1. 返回值,就是函数执行的结果。
    • return后边的代码都不会执行,一旦执行到return语句时,函数将会立刻退出。
    • return后可以跟任意类型的值,可以是基本数据类型,也可以是一个对象。 ```javascript function sum(a,b,c){ return a+b+c; } var result = sum(1,2,3); console.log(“result =”+result);//result = 6

//若 return ;为空 function sum(a,b,c){ var b = a+b+c; return ; } var result = sum(1,2,3); console.log(“result =”+result);//undefined

//return 可以返回任意类型的值 function sum(a,b,c){

//返回字符串,无关传入的参数 return “hello”;

//返回一个对象 var obj={ name : “猪八戒”; eled : “24”; }; return obj;

} var result = sum(1,2,3); console.log(“result = “+result);//result = hello console.log(“a = “+result.name);//a = “沙和尚”

//特殊的 用这种返回值接收的方法查看 alert();函数的返回值 var result = alert(“hello”);//提示框输出为 hello console.log(“result = “+result);//但是,返回结果为 undefined

//返回值是一个函数 function fun(){ function fun4(){ alert(“我是fun4”); } return fun4;//返回的是函数对象,返回结果为 返回结果为function fun4(){} return fun4();//返回值是函数:显示提示框alert,返回结果为undefined; } var a = fun(); fun()();//这种写法等同于 a();//好家伙做了个等量替换

//实现一个判断奇偶性的函数,并通过返回值输出结果 function iso(a){ return a%2==0 ;//“a%2==0”为等式,等式会有正误的判断值 } var result = iso(2); console.log(“result = “+result);//result = ture



4. **立即执行函数**
- 函数定义完立即被使用,这种函数被叫做立即执行函数,形似 ` 函数()`;
- 立即执行函数往往只能使用一次(因为没有储存给变量);
- 立即执行函数还可以进行传参;
```javascript
( function(){
   alert("我是一个匿名函数~");
} )();

//立即执行函数还可以进行传参;
(function(a,b){
  console.log("a = "+a);
  console.log("b = "+b);
})(123,456);
//a = 123;
//b = 456;
  1. . 方法(method)
  • 可以将一个函数设置为一个对象的属性,当一个对象的属性是一个函数时,我们称这个函数是该对象的方法,调用函数就说调用该对象的方法;本来应该是 对象.属性名函数名()

     现在把 属性名部分替换成函数名 -> 对象.函数名()称 `**对象.方法名();**`<br />**      **常见的如:`console.log();`调用console的log方法……
    

    ```javascript //对象的属性可以是任何数据类型,包括函数 var obj = new object; obj.sayname = function(){ console.log(“!!”); } //调用该对象的方法 obj.sayname();

//另外一种创建方法 var obj2 = { name:”sunzi”, age:18, sayname:function(){ console.log(obj2.name); } }; obj2.sayname();// sunzi //对象属性==对象方法(引用函数) //除了函数最后不加分号,其余基本都需要加分号


- **枚举对象中**的**属性**和**属性值**
   - 使用 for…in  语句,对象中有几个属性就会循环几次,并把对象中的每个属性赋值给变量打印出来
   - 语法格式:` for( var 变量 in 对象 ) `
```javascript
var obj = {
   name : "孙",
   age :24,
   address:" 南山南 ",
   gender: "男"
};

for( var n in obj){  
  console.log("取出obj中的属性名:"+ n );
//"name"
//"age"
//"adress"
//"gender"
  console.log("取出属性名的值:"+ obj[n]);
//中括号就是取值
 //    "孙",
 //    24,
 //    南山南 ",
 //    "男"
}
  1. 函数的属性和方法call()apply()
  • 这两个方法都是函数对象的方法需要通过函数对象来调用[ fun()是函数, fun是函数对象]
  • 通过两个方法可以直接调用函数 fun.call(); 等同于 fun.apply(); 等同于 fun();
  • 在调用call()和apply()时可以将第一个对象指定为第一个参数,此时这个对象将会成为函数执行时的this; (即可以通过第一个实参来 修改上下文函数中this指向对象) ```javascript function fun(){

     alert(this.name);//在call()和apply()方法里指定谁就是谁
    

    }

    var obj = {name:”我是obj”}; var obj2 = {name:”我是obj2”};

    //fun();//object window //fun.apply(); //fun.call(obj);//object object fun.call(obj2);//我是obj2


var obj = { name:”我是obj”, sayname:function(){ alert(this.name);//obj }
};

var obj2 = {name:”我是obj2”};

obj.sayname();//obj //apply()传谁指代的就是谁; obj.sayname.apply(obj2);//obj2


   - 不同的是call()是直接传递函数的实参;而apply()需要将实参封装到一个数组[]中传递**arguments**
```javascript

function fun(a,b){
   console.log(a);//2
   console.log(b);//3
}

var obj = {
   name:"我是obj",
   sayname:function(){
      alert(this.name);//obj  }     
};

//call()方法可以将实参在 对象之后依次传递到函数中
fun.call(obj,2,3);

//apply()传参需要封装到一个数组[]中
fun.apply(obj,[2,3]);
  • 在调用函数的时候,浏览器每次都会传递两个隐含的参数:1.this ; 2.封装实参对象 arguments;
  • arguments 在调用函数的时候浏览器给自动传入的一个隐含参数
    • arguments是一个类数组元素,不是数组,可以通过索引来操作数据,也可以获取长度;arguments.length用来获取实参的个数;
    • 它用来封装函数执行过程中的实参(即实参都在这个里面),所以即使不定义形参,也可以通过arguments来使用实参;
    • arguments中有一个属性callee表示当前执行的函数对象 ```javascript function fun(){ //arguments 不是数组 console.log(arguments instanceof Array);//false console.log(Array.isArray(arguments));//false //arguments一些特性 console.log(arguments.length);//2 获取实参长度 console.log(arguments[0]);//hello 获取实参 console.log(arguments[1]);//ture console.log(arguments.callee);//当前执行函数对象fun console.log(arguments.callee == fun);//ture }

fun(“hello”,ture);


- this(调用函数的那个对象)<br />this是函数的上下文对象,根据函数的调用方式不同会执向不同的对象<br />1.以函数的形式调用时,this是window<br />2.以方法的形式调用时,this是调用方法的对象<br />3.以构造函数的形式调用时,this是新建的那个对象<br />4.使用call和apply调用时,this是传入()指定的那个对象<br />5.在全局作用域中this代表window
<a name="f8Jet"></a>
## 4.4 作用域
作用域简单来说就是一个变量的作用范围。<br />在JS中作用域分成两种:<br />1.全局作用域

- 直接在script标签中编写的代码都运行在全局作用域中
- **全局作用域在打开页面时创建,在页面关闭时销毁。**
- 全局作用域中有一个全局对象`**window**`,window对象由浏览器提供,可以在页面中直接使用,它代表的是整个的浏览器的窗口。
   - **在全局作用域中创建的变量都会作为window对象的属性保存**
   - 在全局作用域中创建的函数都会作为window对象的方法保存
   - 在全局作用域中创建的变量和函数可以在页面的任意位置访问。
   - 在函数作用域中也可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量;
- 尽量不要在全局中创建变量
```javascript
//在全局作用域中创建的变量都会作为window对象的属性保存
var a = 10;
var b = "hello";
console.log(window.a);//10

//在全局作用域中创建的函数都会作为window对象的方法保存
function fun(){
console.log("我是fun函数");
}
window.fun();//我是fun函数

//在函数作用域中也可以访问到全局作用域的变量a;
//在全局作用域中无法访问到函数作用域的变量b
var a = 10;
function fun(){
var b = 20;
console.log("a = "+a);
}
fun();//a = 10;
console.log("b = "+b);//b is not undefined

2.函数作用域

  • 函数作用域是函数执行时创建的作用域,每次调用函数都会创建一个新的函数作用域。
  • 函数作用域在函数执行时创建,在函数执行结束时销毁。
  • 在函数作用域中创建的变量,不能在全局中访问。
  • 当在函数作用域中使用一个变量时,它会先在自身作用域中寻找,如果找到了则直接使用,如果没有找到则到上一级作用域中寻找,如果找到了则使用,找不到则继续向上找;如果在全局作用域中都没有则会报错;
  • 在函数作用域中想要直接访问全局变量可以直接使用window对象;

变量的声明提前

  • 在全局作用域中,使用var关键字声明的变量会在所有的代码执行之前被声明,但是不会赋值。
  • 所以可以在变量声明前使用变量。但是不使用var关键字声明的变量不会被声明提前。
  • 在函数作用域中,也具有该特性,使用var关键字声明的变量会在函数所有的代码执行前被声明,
    如果没有使用var关键字声明变量,则变量会变成全局变量 ```javascript var c = 33; function fun(){ //没有使用var关键字,则会默认设置成全局变量 c = 10; d = 100; } console.log(“c = “+c);//c =10; consloe.log(“d = “+d);//d = 100;

var e = 23; function fun(e){ //定义形参相当于在函数作用域中声明了变量 //var e; alert(e); } fun();//undefined

**函数的声明提前**

- 在全局作用域中,使用**函数声明创建的函数(function fun(){}),会在所有的代码执行之前被创建**,
- 即我们可以在函数声明前去调用函数,但是使用函数表达式(var fun = function(){})创建的函数没有该特性

<a name="LDmAG"></a>
## 4.5 this(上下文对象)
我们每次调用函数时,解析器都会将一个上下文对象作为隐含的参数传递进函数。使用this来引用上下文对象,根据函数的调用形式不同,this的值也不同。<br />指向当前对象,this的不同的情况:<br />1.以函数的形式调用时,this是window<br />2.以方法的形式调用时,this就是调用方法的对象<br />3.以构造函数的形式调用时,this就是新创建的对象
```javascript
var name = "全局";

function fun(){
    console.log(this.name);
}

var obj = {
   name  : "孙悟空",
   sayname:fun
};
var obj2 = {
   name  : "沙和尚",
   sayname:fun
};

//想调用obj时,输出孙悟空
obj.sayname();//孙悟空
//想调用obj2的时,输出 沙和尚
obj2.sayname();//沙和尚

4.6 构造函数(对象实例化的一个过程)

  • 使用工厂的方法批量创建对象 ```javascript function fun(name,age,gender){ //添加一个新的对象 var obj = new object(); //添加对象的属性 obj.name = name; obj.age = age; obj.gender = gender;

    //将新的对象返回 return obj; }

var obj2 = fun(“八戒”,24,”男”); var obj3 = fun(“悟空”,25,”女”);


- 我们一般构造对象 用new object(),现在我们想创建一个🐕对象,new Dog(),创建Dog这个过程被称作我们自己 构造函数,构造函数是专门用来**创建对象的函数;**
- **一个构造函数我们也可以称为一个类**
- 通过一个构造函数创建的对象,我们称该对象时这个构造函数的实例,通过同一个构造函数创建的对象,我们称为一类对象
- 构造函数就是一个普通的函数,不同的是 调用方式,且构造函数习惯性首字母大写;
   - 如果直接调用,它就是一个普通函数,如果使用new来调用,则它就是一个构造函数
```javascript
//普通函数
function fun(){ }//创建
var per = fun();//调用
console.log(per);//undefined

//构造函数,在调用的时候多个new
function Fun(){}//创建
var per = new Fun();//调用
console.log(per);//object



function Person(name , age , gender){ //防止对象的属性被写死,用传参
   this.name = name;      //此处的this就是 per 
   this.age = age;      
   this.gender = gender;  
   //向对象中添加一个方法(给对象属性一个函数)
   this.sayName = function(){          
           alert(this.name);     
    }; 
}
//想创建一个新的person 对象;
var per = new Person();
//检查对象per 是否是person的实例
console.log(per instanceof  person);//ture
//Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true
console.log(per instanceof  object);//ture
  • 构造函数的执行流程:
    1.创建一个新的对象
    2.将新的对象作为函数的上下文对象(this),在构造函数中可以使用this来引用新建的对象;
    3.执行函数中的代码
    4.将新建的对象返回
  • instanceof 用来检查一个对象是否是一个类的实例
    语法:对象 instanceof 构造函数
    如果该对象时构造函数的实例,则返回true,否则返回false
  • Object是所有对象的祖先,所以任何对象和Object做instanceof都会返回true
    function Person(name , age , gender){ 
     this.name = name;       
     this.age = age;      
     this.gender = gender;  
     //向对象中添加一个方法
     this.sayName = fun;//fun是指函数本身,fun()是指函数的返回值
    }
    //为解决每调用一次函数就要创建一次sayname方法,
    // 将所有对象共享的sayname方法写到全局变量中
    function fun(){          
             alert(this.name);     
      }; 
    //但是定义在全局变量中,容易污染全局定义域的命名空间,所以引入了原型prototype
    

4.7 原型(prototype)

  • 创建一个函数以后,解析器都会默认在函数中添加一个prototype,prototype属性对应指向的是一个对象,这个对象我们称为原型对象。(每一个函数的原型对象都不相同)
  • 当函数作为构造函数使用,它所创建的对象中 也都会有一个隐含的属性指向该原型对象。这个隐含的属性可以通过对象.__proto__来访问 ;(所以通过构造函数创建出的对像所指向的 prototype 和 函数对象指向的prototype是同一个)

    原型链protohttps://www.yuque.com/u26994639/dz7anq/vhzl1h

function person(){
}
function fun(){
   //创建一个函数
}

//创建一个函数以后,解析器都会默认在函数中添加一个prototype,
//prototype属性对应的是一个对象,这个对象我们称为原型对象。
console.log(fun.prototype);//object
//每一个函数的原型对象都不相同
console.log(person.prototype == fun.prototype);//false

var mc = new fun();
var mc2 = new fun();
//构造函数fun创建的 mc对象中也有一个隐含的属性,通过__proto__来访问
console.log(mc.__pro__);//object
//通过构造函数创建出的对像所指向的 prototype 和 函数对象指向的prototype是同一个
console.log(mc.__pro__ == fun.prototype);//ture
console.log(mc2.__pro__ == fun.prototype);//ture
  • 原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。因此可以将对象中共有的属性和方法统一添加到原型对象中,这样我们只需要添加一次,就可以使所有的对象都可以使用。原型对象也是对象,所以它也有原型。
    • 当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,如果在自身中找到了,则直接使用 ; 如果没有找到,则去原型对象中寻找,如果找到了则使用,
    • 如果没有找到,则去原型的原型中寻找,依此类推。直到找到Object的原型为止,Object的原型的原型为null,如果依然没有找到则返回undefined ; ```javascript //向fun的原型prototype中添加共有属性a fun.prototype.a = 123; //此时 对象mc可以在原型公共区域中也能找到属性a=123 console.log(mc.a);//123

//向fun的原型prototype中添加共有方法, fun.prototype.sayhello = function(){ alert(“hello”); } console.log(mc.sayhello);//hello

//原型对象也是对象,所以它也有原型 console.log( mc.proto.proto.hasOwnProperty(“hasOwnProperty”) );


- **hasOwnProperty()这个方法可以用来检查对象自身中**是否含有某个属性<br />语法:对象.hasOwnProperty("属性名")
```javascript
function fun(){
 }
//向原型中添加一个name属性
fun.prototype.name = "sun";

var mc = new fun();
//用in检查对象中是否含有某个属性,如果对象本身中没有但是原型中有,也会返回ture
console.log("name" in mc);//ture

//用hasOwnProperty()来检查 对象本身是否有该属性
console.log( mc.hasOwnProperty("name") );//false

4.8 toString方法

当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值
如果我们希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法

//修改Person原型的toString   
Person.prototype.toString = function(){       
    return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]";  
};

4.9 垃圾回收(GC)

  • 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,所以这种垃圾必须进行清理。528507304550790601.jpg
  • 在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的操作,我们需要做的只是要将不再使用的对象设置null即可;

五、数组(Array)

数组也是一个对象,是一个用来存储数据的对象和Object类似,但是它的存储效率比普通对象要高;
数组中保存的内容我们称为元素,在对象中称为属性;数组使用数字作为索引(index)来操作元素;
索引指由0开始的整数;

5.1 数组的操作:

  • 创建数组
    • **var** arr = **new** Array();
    • **var** arr = [];
  • 向数组中添加元素
    • 语法: 数组对象[索引] = 值;
    • arr[0] = 123; arr[1] = "hello";
  • 创建数组时直接添加元素
    • **var arr = [元素1,元素2....元素N]; **
    • var arr = new Array(元素1,元素2....元素N);
    • 元素之间用逗号隔开,数组中的元素可以是任意数据类型
    • 例子: var arr = [123,”hello”,true,null,undefined];
  • 获取和修改数组的长度数组.length; 当数组连续的时候 ,length获取到的是数组中元素的个数 ; 当数组是非连续的时候 数组.length 获取到的是数组的 最大索引+1 ; ```javascript arr[0] = 10; arr[1] = 15; arr[2] = 16; arr[10] = 25;

//当数组是非连续的时候 数组.length 获取到的是数组的 最大索引+1 ; console.log(arr.length);//11

//读取不存在的数组,返回值是undefined console.log(arr[5]);//undefined

//向数组的最后添加元素 arr[arr.length] = 50;

//创建数组,并向数组中添加元素 var arr = [1,2,3,4,5,6,7,8,9]; //使用构造函数创建数组的时候,也可以同时添加元素,元素作为函数的参数传递 var arr = new array(1,2,3,4,5,6,7,8,9);

//创建一个数组,数组中只有一个元素10 arr = [10]; //创建一个长度为10的数组 arr = new array(10);//,,,,,,,,,

//数组中的元素可以是任意数据类型,当然也可以是对象 //创建一个对象 var obj = {name : “sun”}; arr[arr.length] = obj; console.log(arr[arr.length].name);//sun

arr = [ {name : “sun”},{name : “sha”},{name : “bajie”} ]; console.log(arr[0].name);//sun

//数组中的元素可以是任意数据类型,当然也可以是函数 arr = [ function(){alert(1)}, function(){alert(2)}, function(){alert(3)} ]; //调用 arr0;

//数组中放数组,即二维数组 arr = [[1,2,3],[4,5,6], [7,8,9]]; console.log(arr);//1,2,3,4,5,6,7,8,9打印数组 console.log(arr[0]);//1,2,3


- 修改数组的长度  `数组.length = 新长度`<br />如果修改后的length大于原长度,则多出的部分会空出来<br />如果修改后的length小于原长度,则原数组中多出的元素会被删除
- 向数组的最后添加元素 `数组[数组.length] = 值;` 
<a name="fEJYu"></a>
## 5.2 数组的方法
| **functionName** | **function** | **usage** |
| --- | --- | --- |
| push() | 向数组的**末尾**添加一个或多个元素,并返回数组新的长度 | 语法:数组.push(元素1,元素2,元素N); |
| pop() | 删除并返回数组的最后一个元素 | 语法:arr.pop(); |
| unshift() | 向数组的**开头**添加一个或多个元素,并返回数组的新的长度 | 语法:arr.unshift("元素"); |
| shift() | 删除并返回数组的开头第一个元素 | 语法:arr.shift(); |
| reverse() | 可以用来**反转**一个数组,它会对原数组产生影响 |  |
| concat() | 可以**连接**两个或多个数组,它不会影响原数组,而是新数组作为返回值返回 | 备注:不仅可以传数组也可以传其他数据 |

```javascript
//创建一个数组
var arr = ["老大","老二","老三"];

//使用push()向数组的末尾添加一个或多个元素,并将数组新的长度作为返回值返回
var len = arr.push("八戒","唐僧");
console.log("len = "+ len);//len = 5



//使用pop()删除并返回数组的最后一个元素
arr.pop();
console.log(arr);//"老大","老二","老三","八戒"
arr.pop();
arr.pop();
console.log(arr);//"老大","老二"
var delete = arr.pop();
console.log("delete = "+delete);//delete = 老二




//使用 concat()连接多个数组,并将新的数组返回
var arr = ["老大","老二","老三"];
var arr2 = ["唐僧","八戒"];
var arr3 = ["皇后","皇上"];

var res = arr.concat(arr2);
console.log(res);//"老大","老二","老三","唐僧","八戒"

//不仅可以传数组也可以传其他数据
var res = arr.concat(arr2,arr3,"白雪公主");
console.log(res);//"老大","老二","老三","唐僧","八戒","皇后","皇上","白雪公主"

1. .slice(sart,[end])

  • 从一个数组中截取指定的元素 ;
  • 该方法不会影响原数组,而是将截取到的内容封装为一个新的数组并返回 ;
  • 参数:1.截取开始位置的索引(包括开始位置) 2.结束位置索引(不包括最后位置);

    • 第二个参数可以省略不写,如果不写则一直截取到最后
    • 参数可以传递一个负值,如果是负值,则从后往前数
      var arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
      var newarr = arr.slice(0,2);
      console.log(newarr);//"孙悟空","猪八戒"
      

      2. .splice()

  • 用来删除数组中指定元素,并使用新的元素替换 ,插入

  • 该方法会将影响原数组的元素,并将删除的元素作为返回值返回
  • 参数:1.删除开始位置的索引 2.删除的个数 3.第三个以后都是替换的元素,这些元素将会插入到开始位置索引的前边
  • 还可以应用于 在指定位置插入元素,只需让第二个删除参数长度为0即可; ```javascript var arr = [“孙悟空”,”猪八戒”,”沙和尚”,”唐僧”,”白骨精”]; var newarr = arr.splice(0,2); console.log(arr);//“沙和尚”,”唐僧”,”白骨精” console.log(newarr);//“孙悟空”,”猪八戒”

//引入第三个参数的作用 var arr = [“孙悟空”,”猪八戒”,”沙和尚”,”唐僧”,”白骨精”]; var newarr = arr.splice(0,1,”铁扇公主”,”牛魔王”);//从索引位置0开始删除1个元素,并在0位置插入两个新的元素 console.log(arr);//“铁扇公主”,”牛魔王”,”猪八戒”,”沙和尚”,”唐僧”,”白骨精” console.log(newarr);//“孙悟空”

//还可以应用于 在指定位置插入元素,只需让第二个删除参数长度为0即可; var arr = [“孙悟空”,”猪八戒”,”沙和尚”,”唐僧”,”白骨精”]; var newarr = arr.splice(3,0,”铁扇公主”,”牛魔王”); console.log(arr);//“孙悟空”,”猪八戒”,”沙和尚”,”铁扇公主”,”牛魔王”,”唐僧”,”白骨精” console.log(newarr);// “”空

```javascript
        //数组去重练习
        var arr = [1,2,3,2,2,2,1,3,4,2,5];

        for(var i=0;i<arr.length;i++){

            for(var j=i+1;j<arr.length; j++){

                var flag = 0;

                if(arr[i] == arr[j]){ 
                     //若有相同元素,则删除后边的相同元素
                    arr.splice(j,1);
                    //注意连续相同的情况,删除j元素后会自动补位,此时将不会再比较这个补位的元素,从而出现漏检验的情况
                   // if(arr[i] == arr[j]) 
                     j--;
                }
            }

        }

        console.log(arr);

3. join([splitor])

  • 可以将一个数组转换为字符串;
  • 参数:需要一个字符串作为参数,这个字符串将会作为连接符来连接数组中的元素
    如果不指定连接符则默认使用,逗号链接 ```javascript var arr = [“孙悟空”,”猪八戒”,”沙和尚”,”唐僧”,”白骨精”];

//如果不指定连接符则默认使用,逗号链接 arr.join(); console.log(arr);//“孙悟空,猪八戒,沙和尚,唐僧,白骨精”

//需要一个字符串作为参数,这个字符串将会作为连接符来连接数组中的元素 arr.join(“-“); console.log(arr);//“孙悟空-猪八戒-沙和尚-唐僧-白骨精”

<a name="oNqGJ"></a>
### 4.  . sort()

- 可以对一个数组中的内容进行排序,默认是按照Unicode编码进行排序
   - 即使对于纯数字排序也会按照Unicode编码进行排序,所以可能会得到错误的结果;
```javascript
var arr = [7,4,11,2,59];
        arr.sort();
        //数字unicode 1-9对应 0x30-0x39
        console.log(arr);// 11 2 4 59 7
//只比较了第一位数字
  • 调用以后,会直接修改原数组。
  • 可以自己指定排序的规则,需要一个回调函数function(){}作为参数:

    • 我们可以在sort()添加一个回调函数,来指定排序规则,回调函数中需要定义两个形参a,b,
      浏览器将会分别使用数组中的元素作为实参去调用回调函数, 使用哪个元素调用不确定,但是肯定的是在数组中a一定在b前边
    • 浏览器会根据回调函数的返回值来决定元素的顺序,

      • 如果返回一个大于0的值,则元素会交换位置
      • 如果返回一个小于0的值,则元素位置不变
      • 如果返回一个0,则认为两个元素相等,也不交换位置
      • 结论: return a-b;//升序

                                   return b-a;//降序
        

        ```javascript var arr = [4,5];

//升序 arr.sort( function(a,b){ //若前边的元素大,交换 if(a>b) return 1; //若前边的元素小,不动 else if(a<b) return -1; //相等 else return 0; } )

//结论 arr.sort( function(a,b){ return a-b;//升序 return b-a;//降序 } )


<a name="R53SV"></a>
## 5.3 遍历数组

- 遍历数组就是将数组中元素都获取到,一般情况我们都是使用for循环来遍历数组

**       for**(**var** i=0 ; i<数组.length ; i++){       //数组[i]   }  
```javascript
 <script type="text/javascript">

        //构造函数
        function person(name,age,gender){
            this.name = name;
            this.age = age;
        }
        //修改person的原型tostring
        //在直接输出对象的时候,实际上输出的是字符串toString方法的返回类型object,我们希望输出的是对象的值,所以修改toString()的返回值
        person.prototype.toString = function(){       
          return "Person[name="+this.name+",age="+this.age+"]";  
        }; 

        //创建person对象
        var per = new person("孙悟空",18);
        var per2 = new person("八戒",28);
        var per3 = new person("和尚",8);
        var per4 = new person("二郎神",16);
        var per5 = new person("白骨精",38);

        //将这些对象放入数组中
        var perarr = [per,per2,per3,per4,per5];

        //在一个函数中实现,将perarr数组中年龄大于18的perso封装到一个新的数组中
        function getadult(arr){//arr形参,要提取信息的数组
           //创建一个新的数组
           var newarr = [];
           var k = 0;
           //遍历数组
           for(var i=0; i<arr.length; i++){
             //console.log(arr[i]);
              if(arr[i].age >= 18){
                newarr.push( arr[i] );
              }
           }
           return newarr;
        }

        //可以用字面量接受一个数组的值
        var result = getadult(perarr);
        console.log(result);

    </script>
  • 使用forEach()方法来遍历数组(不兼容IE8)

    • 数组.forEach(function(value , index , obj){ });
    • forEach()方法需要一个(匿名)回调函数作为参数,数组中有几个元素,回调函数就会被调用几次,
      每次调用时,都会将遍历到的信息以实参的形式传递进来,我们可以定义形参来获取这些信息。
      value:正在遍历的元素
      index:正在遍历元素的索引
      obj:整个数组的元素,被遍历对象
      var arr = ["孙悟空","猪八戒","沙和尚","唐僧","白骨精"];
      arr.forEach( function(value, index,obj){
       console.log(value);//"孙悟空","猪八戒","沙和尚","唐僧","白骨精"
       console.log(index);// 0 1 2 3 4 
       console.log(obj);  //"孙悟空","猪八戒","沙和尚","唐僧","白骨精"
                          //"孙悟空","猪八戒","沙和尚","唐僧","白骨精"
                          //"孙悟空","猪八戒","沙和尚","唐僧","白骨精"
                          //"孙悟空","猪八戒","沙和尚","唐僧","白骨精"
                          //"孙悟空","猪八戒","沙和尚","唐僧","白骨精"
      } )
      

      六、常用类及其方法

      包装类

  • 在JS中为我们提供了三个包装类:String() Boolean() Number() 通过这三个包装类将 基本数据类型的数据 转换为 对象;(首字母大写);

  • 基本对象 比 基本数据类型的 可应用属性、方法,功能更强大; ```javascript var num = new Number(2); // 创建一个Number类型的对象 console.log(typeof num);// object var str = new String(“hello”);
    var bool = new Boolean(true);

//向对象中添加一个属性 num.hello = “abcde”; console.log(num.hello);//abcde //给基本数据类型添加一个属性 var a.hello = “jjj” ; console.log(a.hello);//undefined

//但是对象有缺点,数据完全相等的情况下两个对象做比较也是不相等的,因为对象比的是地址 var num = new Number(2); var num2 = new Number(2); console.log( num == num2 );//false


- 但是在实际应用不会这么用,如在进行对象比较的时候,会有不可预期的结果;当我们去操作一个基本数据类型的属性和方法时,**解析器会临时使用包装类将其转换为对象,然后再去操作属性和方法,**操作完成以后再将这个临时对象进行销毁。
- 主要是为了给浏览器临时使用
<a name="rMWuO"></a>
## 6.1 Date
日期的对象,在JS中通过Date对象来表示一个时间<br />创建对象<br />创建一个**当前实时**的时间对象<br />` **var** d = **new** Date(); `<br />创建一个**指定的**时间对象<br />`**var** d = **new** Date("月/日/年 时:分:秒");  `<br />**Date的. 方法:(注意大写是必须的)**

| **name** |  |
| --- | --- |
| getDate() | 当前日期对象应该属于几号的(1-31) |
| getDay() | 返回当前日期对象应该属于周几(0-6)0是周天 |
| getMonth() | 返回当前日期对象应该属于哪个月份(0-11)0表示1月,1表示2月… |
| getFullYear() | 从 Date 对象以四位数字返回年份。 |
| getHours() | 返回 Date 对象的小时 (0 ~ 23)。 |
| getMinutes() | 返回 Date 对象的分钟 (0 ~ 59)。 |
| getSeconds() | 返回 Date 对象的秒数 (0 ~ 59)。 |
| getMilliseconds() | 返回 Date 对象的毫秒(0 ~ 999)。 |
| getTime()<br />console.log(time/1000/60/60/24/365);年 | 返回当前日期对象的时间戳<br />时间戳,指的是从1970年月1日 0时0分0秒,**到现在时间的毫秒数(1秒=1000毫秒)**<br />计算机底层保存时间都是以时间戳的形式保存的。 |
| Date.now()  常用于测试性能 | 可以获取**当前代码行执行**时的时间戳 |

```javascript
//用于获取当前代码行执行时的时间戳;(以毫秒为单位的)
var start = Date.now();

for(var i=0 i<100; i++){
 console.log(i);
}

var end = Date.now();

console.log("执行了:"+ (end - start) +"毫秒");

6.2 Math

Math属于一个工具类,它不需要我们创建对象,它里边封装了属性运算相关的常量和方法
我们可以直接使用它来进行数学运算相关的操作方法: Math.PI 常量,圆周率

  • Math.abs() 绝对值运算
  • Math.ceil() 向上取整 ; 小数部分只要有值就进1
  • Math.floor() 向下取整 ;直接舍弃小数部分
  • Math.round() 四舍五入取整 ;
  • Math.random() 生成一个0-1之间的随机数
  • Math.round(Math.random()*(y-x)+x); 生成一个x-y之间的随机数
  • Math.pow(x,y) 求x的y次幂
  • Math.sqrt() 对一个数进行开方
  • Math.max() 求多个数中最大值
  • Math.min() 求多个数中的最小值
//PI 属于Math属性
console.log(Math.PI);//3.1415926535

//Math方法
console.log(Math(-1)); // 1
console.log(Math.ceil(1.00002432)); // 2
console.log(Math.random()*x);//生成 0 - x 之间的随机数
//生成 x - y 之间的随机数
console.log(Math.random()*4+2);//2-6之间的随机数
  • 777669882194278083.jpg

    6.3 字符串String的相关的方法

  • 在底层字符串是以字符数组的形式保存的[“H”,”e”,”l”] ;
  • 使用ES6中的字符串新方法

String.prototype.padStart(maxLength, fillString=’’)String.prototype.padEnd(maxLength, fillString=’’)来填充字符串;

  • length 获取字符串的长度
  • charAt() 根据索引获取指定的字符 == str[x]
  • charCodeAt() 根据索引获取指定的字符编码
  • String.fromCharCode() 根据字符编码获取字符 ```javascript //String.fromCharCode() 根据字符编码获取字符 console.log(String.fromcharCode(74));// H

//indexOf() str = “hello”; result = str.indexOf(“e”); console.log(result);// 1

str = “hellooookkkkk”;//从第x个位置开始查找 result = str.indexOf(“e”,10); console.log(result);// -1


- indexOf() 是从前向后找<br />lastIndexOf()  是从后向前找<br />从一个字符串中检索指定内容, 如果找到该内容,则会返回其第一次出现的索引,如果没有找到则返回-1 ; 可以指定一个第二个参数,来表示开始查找的位置;
- slice(start,[end])<br />从一个字符串中截取指定的内容,并将截取到内容返回,不会影响原变量<br />参数:<br />第一个:截取开始的位置(包括开始)<br />第二个:截取结束的位置**(不包括结束)**<br />可以省略第二个参数,如果省略则一直截取到最后<br />可以传负数,如果是负数则从后往前数
- substr()<br />和slice()基本一致,不同的是它第二个参数不是索引,而是截取的长度数量
- substring()<br />和slice()基本一致,不同的是它不能接受负值作为参数,如果设置一个负值,则会自动修正为0,<br />**substring()中如果第二个参数小于第一个,自动调整位置**
- toLowerCase()<br />将字符串转换为小写并返回
- toUpperCase()<br />将字符串转换为大写并返回
<a name="M77TF"></a>
### 6.3.1 正则表达式在字符串中的应用

1. **split()**
- 可以根据指定内容将一个字符串**拆分为一个数组**<br />参数:需要一个字符串作为参数,将会根据字符串去拆分数组,这个字符串就可以接收一个正则表达式,此时变成了根据正则表达式去拆分数组;
- 自动匹配搜索全局,不需要在正则表达式中再使用 全局匹配 g
2. **match()**
- 可以根据正则表达式,从一个字符串中将**符合条件的内容提取出来并返回 ;**
- 默认情况下我们的match只会找到第一个符合要求的内容,找到以后就停止检索,此时设置正则表达式为全局匹配模式g,这样就会匹配到所有的内容 ;
- 可以为一个正则表达式设置多个匹配模式 `**/gi** 既全局匹配又忽略大小写`,且顺序无所谓
- match()会将匹配到的内容封装到一个数组中返回,即使只查询到一个结果
3. **replace()**<br />可以将字符串中**指定内容替换为新的**内容<br />参数:<br />1.被替换的内容,可以接受一个正则表达式作为参数<br />**2.**新的内容 空串则为删除""<br />默认只会替换第一个
3. **search()**
- 可以**搜索字符串中是否含有指定内容**,搜索到的返回值为第一次出现的索引位置,没有搜索返回-1;
- 它可以接受一个正则表达式作为参数,然后会根据正则表达式去检索字符串
- serach()只会查找第一个,即使设置全局匹配g也没用 ;
- 加入正则以后可以同时检索多个符合要求条件;
```javascript
//1.split()
var str  = "1a2b3c4d5e6";
var result = str.split(/[A-z]/);
console.log("result");//"1,2,3,4,5,6"


//2.match()
var str  = "1a2b3c4d5e6";
var resule = str.match(/[A-z]/);
console.log(result);//a
var resule = str.match(/[A-z]/g);//设置为全局匹配模式
console.log(result);//a,b,c,d,e
//match()的返回结果是一个数组
console.log(Array.isArray(result));//ture
//被封装到数组里后在一些时候的操作会更简单
console.log(result[2]);// c

//3.replace()
var str  = "1a2b3c4d5e6";
var result = str.replace(/[A-z]/gi,"");
console.log("result");//"123456"

//4.search()
str = "hello abc hello aec afc";
result = str.search(/a[bef]c/);//要求 搜索abc或者afc 或者aec
console.log(result);//返回检索到的第一个abc的索引 6

七、正则表达式

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

1. 语法

  • **var 变量 = new RegExp("正则","匹配模式"); **``使用构造函数创建正则表达式灵活;
    • 注意:使用构造函数时,由于它的参数是一个字符串,而\是字符串中转义字符,如果要使用\则需要使用 \来代替
    • 例如:var reg = new RegExp(“a”);这个正则表达式 用来检查一个字符串种是否含有”a”;
  • **var reg = /正则表达式/匹配模式;**``使用字面量来创建正则表达式简洁
    • 匹配模式可以多个一起写:
      • 或 |[] 任意[^ ] 除了
  • 使用typeof检查正则对象,会返回 object ; 元符号
  • 检查一个字符串中是否含有 . . 表示任意字符
  • 在正则表达式中使用\作为转义字符
  • [a-z]任意小写,[A-z]任意字母,[0-9]任意数字、[A-z0-9]任意字母数字
  • 检查 . 用. \用\

\w 任意字母、数字、下划线 [A-z0-9]
\W 除了字母、数字、下划线 [ ^A-z0-9]
\d 任意的数字 [0-9]
\D 除了数字 [ ^0-9]
\s 空格
\S 除了空格
\b 单词边界
\B 除了单词边界 量词(次数的重复性)

  • 通过量词可以设置一个内容出现的次数,量词只对它前边的一个内容起作用
  • {n}正好出现n次 {m,n}出现m到n次 {m,}m次以上
  • + 至少一个,相当于{1,} *0个或多个,相当于{0,} ? 0个或1个,相当于{0,1} 边界表达式(开头结尾的要求)(不要在java中用,javaScript中用)
  • ^:正则开始, 检查一个字符串中是否以a开头:reg = /^a/;
    $:正则结束 :注意结束前一个才是结束匹配 reg = /b$/;以为a为结尾;
  • 特殊的在正则表达式中同时使用 ^和$则要求字符串完全符合正则表达式的值;reg = /^a$/; //a; 第二个参数 gi
  • 在构造函数中可以传递一个匹配模式 作为第二个参数;设置匹配模式时,可以都不设置,也可以设置1个,也可以全设置,设置时没有顺序要求 ;
    • i:忽略大小写(ignore)
    • g:全局匹配模式(默认为1次) ```javascript //判断手机号的合法性 //手机规则: //1.首位开头是1; //2.第二位是 3-9; //3.第三位往后是任意9个数字; var phone = “18353665199”; var reg = /^1[3-9][0-9]{9}$/; console.log(reg.text(phone));//ture var phone = “28353665199”; console.log(reg.text(phone));//flase

//去掉字符串中的空格,可以采用替换的思路 var str = “ hel lo “; str = str.replace(/\s/g,””);//“hello” 用””代替空格 //若只去除字符串的 开头和结尾的空格 str = str.replace(/^\s*/,””);//“hello”

//邮件的正则(就是用机器语言将电子邮件的格式翻译出来) //eg: hello .nihao @ abc .com .cn // 任意字母数字下划线 .任意字母数字下划线 @ 任意字母数字 .任意字母(2-5) // \w{3,} (.\w+) @ [A-z0-9]+ ([A-z]{2,5}){1,2} var str = /^\w{3,}(.\w+)@[A-z0-9]+([A-z]{2,5}){1,2}$/; var email = “1290@qq.com”; console.log( str.text(email) );//ture


- 一般会有整理好的 通用正则表达式
<a name="qsd9P"></a>
## 2. **test()**方法:
**test()** 可以用来检查一个字符串是否符合正则表达式,如果符合返回true,否则返回false;
```javascript
//检查一个字符串是否符合正则表达式,如果符合返回true,否则返回false;
var reg = new RegExp("aa");
var str = "aa";
var result = reg.test(str);
console.log(result);// ture

var reg = new RegExp("a");
//var reg = new RegExp("a");这个正则表达式 用来检查一个字符串种是否含有"a";
console.log( reg.test("sbadd") );// ture
//区分大小写
console.log( reg.test("sbAdd") );// false

//去掉两端的空格:
var s = "            f    afa    ";    s = s.replace(/^\s*|\s*$/g,""); 


var reg = new RegExp("a");
//检查一个字符串种是否含有"a";并忽略大小写;
console.log( reg.test("sbAdd","i") );// 

//两种模式
var reg = new RegExp("a","i");
//等同于
var reg = /a/i;

//或者,任意
var reg = /a|b|c/;//字符串中含有a或b或c
var reg = /[A-Z]/;//字符串中 A-Z中任意字符都可以

//^
reg = /[^0-9]/;//除了数字
consolg.log( reg.test("123") );//false
consolg.log( reg.test("1a23456") );//ture

//量词
reg = /ab{1,9}/;//b出现1到9次
reg = /ab+/;//b至少出现1次
reg = /ab?/;//b出现0次或1次

//元符号 \b单词边界
reg = /child/;
console.log(reg.text("hello children"));//ture
//想检查单词child,而非一个单词中含有某部分
reg = /\bchild\b/;
console.log(reg.text("hello children"));//false

八、DOM

  • Document Object Model文档对象模型,通过DOM可以来任意来修改网页中各个内容;换言之:HTML DOM 是关于如何获取、更改、添加或删除 HTML 元素的标准
  • 文档: 文档指的是网页,一个网页就是一个文档;
  • 对象: 对象指将网页中的每一个节点都转换为对象,转换成对象以后,就可以以一种纯面向对象的形式
  • 操作网页,对对象进行属性和方法的操作;
  • 模型:模型用来表示节点和节点之间的关系,方便操作页面 ;DOM树
  • 节点(Node):节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点,虽然都是节点,但是节点的类型却是不同的 ;
  • 常用的节点

    • 文档节点 (Document),代表整个网页
    • 元素节点(Element),代表网页中的标签
    • 属性节点(Attribute),代表标签中的属性
    • 文本节点(Text),代表网页中的文本内容0. javascript初级版 - 图8

      1.DOM操作

      元素 = = 标签
    • ; name为属性
  • 在网页中浏览器已经为我们提供了document文档对象它代表的是整个网页,它是window对象的属性,可以在页面中直接使用。

  • 通过document对象查询方法:
    根据元素的id属性查询一个元素节点对象:
    document.getElementById("id属性值");
    根据元素的name属性值查询一组元素节点对象:
    document.getElement**s**ByName("name属性值");
    根据标签名(div、h1)来查询一组元素节点对象:
    document.getElement**s**ByTagName("标签名");
  • innerHTML :使用该属性可以获取或设置元素内部的HTML代码; 但是对于自结束标签(如input)没用;
  • 读取元素的属性:元素.属性名`` ele.name``inputs[i].id``ele.value ele.className
  • class属性不能采用这种方式,读取class属性时需要使用 **元素.classNam**e
  • 修改元素的属性:元素.属性名 = 属性值 ```javascript

    which city do you like ?

    • 北京
    • 上海
    • 东京
    • 首尔


    which game do you like?

    • 红警
    • 实况
    • 极品飞车
    • 魔兽


    which operation on your phone?

    • ios
    • android
    • windows

    gender: male:

    name:


    <a name="jXzWx"></a> ## 2. 事件(Event) - 事件指的是用户和浏览器之间的**交互行为,在事件对应的属性中设置一些js代码,这样当事件被触发的时候,这些代码将会被执行**。比如:点击按钮这个动作、关闭窗口这个操作、鼠标移动这个行为…我们可以为事件来绑定回调函数来响应事件。 - **绑定事件的方式:** - 1.可以在标签的事件属性中直接设置相应的JS代码;但是这种写法被称为结构和行为的耦合,不方便维护;例子:<button onclick="alert("点我干嘛")">按钮</button> - 2.可以通过为对象的指定事件属性设置**回调函数**的形式来处理事件(推荐使用);javascript //可以为按钮的对应事件 绑定一个处理函数形式 来响应事件 //这样当事件被触发的时候(例如按钮按下),其对应的函数就会被调用

    - **文档的加载**<br />浏览器在加载一个页面时,是按照自上向下的顺序加载的,加载一行执行一行。如果将js代码编写到页面的上边,当代码执行时,页面中的DOM对象还没有加载,此时将会无法正常获取到DOM对象,导致DOM操作失败。 - 解决方式一:可以将js代码编写到body的下边javascript


    //根据元素的id属性查询一个元素节点对象

    
       - 解决方式二:js 写在head体里,为window绑定onload事件<br />将js代码编写到`window.onload = function(){}`中;window.onload 对应的回调函数会在整个页面加载完毕以后才执行,所以可以确保代码执行时,DOM对象已经加载完毕了
    ```javascript
    <script>       
      window.onload = function(){          
      var btn = document.getElementById("btn");          
      btn.onclick = function(){ 
        alert("123");
      };       
    };  
    </script>
    
    //本质上就是在 获取对象,操作对象这两步进行
    <head>  
    <style>
    
            #outer{
                width: 500px;
                margin: 50px auto;
                padding: 10px;
                background-color: turquoise ;
                text-align: center;
            }
    
            img{
                width: 500px;
                height: 400px;
            }
        </style>
    
           <!-- JS  -->
          <script type="text/javascript">
              window.onload = function(){
    
                    //获取按钮对象
                     var prev = document.getElementById("prev");
                     var next = document.getElementById("next");
    
                    //本质上切换图片就是要修改 img 标签的src属性
                    var img = document.getElementsByTagName("img")[0];
                    //创建一个数组 用来保存图片的路径
                    var arr = ["./img/1.jpeg","./img/2.jpeg","./img/3.jpeg","./img/4.jpeg"];
    
                    var index = 0;
    
                    var page = document.getElementById("page");
                    page.innerHTML = "一共" + arr.length + "张图片,当前是第" + (index+1)+ "张" ;
    
                    //分别给两个按钮绑定 相应函数
    
                    prev.onclick = function(){
                        index--;
                        if(index < 0)
                        index = arr.length - 1 ; 
                        img.src = arr[index];
    
                        page.innerHTML = "一共" + arr.length + "张图片,当前是第" + (index+1)+ "张" ;
                    };
    
                    next.onclick = function(){
                        index++;
                        if(index > arr.length - 1)     index = 0 ; 
                        img.src = arr[index];
    
                        page.innerHTML = "一共" + arr.length + "张图片,当前是第" + (index+1)+ "张" ;
                    };
    
    
    
              };
          </script>
    </head>
    <body>
         <div id="outer">
             <p id="page"> </p>
    
             <img src="./img/1.jpeg" alt="冰棍">
    
             <button id="prev">上一张</button>
             <button id="next">下一张</button>
         </div>
    </body>
    

    3. DOM查询

    获取元素节点的子节点(通过具体的元素节点调用)

    • 元素.getElementsByTagName() -方法 通过标签名查询当前元素的指定后代元素,子节点包括便签元素中的文本,子元素自包含标签元素 getElementsByTagName ()详解getElementsByTagName():方法的用途是寻找有着给定标签多的所有的元素。
      element=document.gatElamentsByTagName( tagName);

    • 这个方法返回一个节点的集合,这个集合可以当做一个数组来处理。这个集合的length属性等于当前文档里有着给定标签名的所有元素的总个数。这个数组里面的每个元素都是一个对象,他们都有着nodeName、nodeType、parentNode、childNodes等属性。

    • 下面的例子将把当前文档里的所有文本段元素(p元素)全部搜索出来,getElementsBuTagName()方法返回的节点集合的length属性将被保存到变量howmany里:

    war paras = document.getElementsByTagName(“”p”); var howmany = paras.llength;

    • 在getElementsByTagName()方法返回成功后,比较常见的后续手段是用一个for循环去遍历这个方法所有返回的集合里面的各个元素,在for循环里,我们可以使用setAttribute()、clone()或appendChild()等方法对各个有关元素进行查询处理。

    下面的例子将遍历当前文件里面的所有文本段元素,并将其title属性全部设置为空字符串:
    war paras = document.getElementsByTagName(“p);
    for ( var i=O,ieparas.lengthi++ ){
    paras[i].sctAttribute(title”.””);}

    • 在上例中,变量paras的数据类型是nodeList。这个集合里的每一个元素可以像其他任何一个数组那样进行访问: paras[0]、paras[1]、paras[2]等等。当然也可以使用item()方法: paras.item[0]等等
    • getElementsByTagName()方法不必非得用在整个文档上,他也可以用来在某个特定的元素的子节点当中寻找持有者给定标签名的元素。

    在下例中,在当前文档里包含着一个id属性值是content元素,为了找出content元素所包含的所有p文本段元素,我们把getElementsByTagName()方法用在了content上:
    war container = document.gctElementByld(“content”);
    var paras = container .getElementsByTagName(“p”);
    war hawmany = paras.length;
    执行完上面的这些语句后,变量howmany的值将是包含在content元素里的所有文本元素的总分数,而不是包含在文档里面文本段总个数。

    • 元素.childNodes -属性获取当前元素的所有子节点会将 空白的文本子节点 也当成节点获取进来

    childNodes属性会获取包括文本节点在的所有节点,根据DOM标签标签间空白也会当成文本节点
    注意:在IE8及以下的浏览器中,不会将空白文本当成子节点,所以该属性在IE8中会返回4个子元素而其他浏览器是9个(所以一般用 .children属性比较好 )

    • 元素.children 获取当前元素的所有子元素(节点是属于js里的概念,元素是属于css里的概念)
    • 元素.firstChild获取当前元素的第一个子节点,会获取到空白的文本子节点
    • 元素.lastChild获取当前元素的最后一个子节点

      ///获取子节点 4-6
            //为id是 btn04的按钮 绑定一个单击响应函数
            var btn04 = document.getElementById("btn04");
            btn04.onclick = function(){
                 //查找 id为city 下的所有li 节点
                 //找到 city
                 var city = document.getElementById("city");
                 //继续找(获取) city-下的 li 
                 var lis = city.getElementsByTagName("li");
                 //这个谁的.有种属于它的感觉,从中获取
                 for(var i=0; i<lis.length; i++){
                    alert(lis[i].innerHTML);
                 }
            }
      
            //为id是 btn05的按钮 绑定一个单击响应函数
            var btn05 = document.getElementById("btn05");
            btn05.onclick = function(){
                 //返回 #city下的所有子节点
                 var city = document.getElementById("city");
                 //var childdren = city.childNodes;
                 var cns =  city.children;
                 alert(cns.length);//4
            }  
      
            //为id是 btn06的按钮 绑定一个单击响应函数
            var btn06 = document.getElementById("btn06");
            btn06.onclick = function(){
                 //返回phone 的第一个子节点
                 var phone = document.getElementById("phone");
                 var cns2 = phone.firstChild;
                 //注意 返回的第一个子节点 是空格所以 显示 undefined,
                 //删除body中的 空白文本(即回车换行)
                 alert(cns2.innerHTML);//ios
            }
      
    • 元素.parentNode获取当前元素的父元素

    • 元素.previousSibling获取当前元素的前一个兄弟节点
    • previousElementSibling获取前一个兄弟元素,IE8及以下不支持
    • 元素.nextSibling获取当前元素的后一个兄弟节点
    • firstElementChild获取当前元素的第一个子元素,firstElementChild不支持IE8及以下的浏览器,
      如果需要兼容他们尽量不要使用
    • innerHTMLinnerText
      这两个属性并没有在DOM标准定义,但是大部分浏览器都支持这两个属性,两个属性作用类似,都可以获取到标签内部的内容,不同是innerHTML会获取到html标签,而innerText会自动去除标签
      如果使用这两个属性来设置标签内部的内容时,没有任何区别的
    • 读取标签内部的文本内容元素.firstChild.nodeValue ```javascript window.onload = function(){

      //发现 获取对象的 和 对对象设置回调函数的步骤总是重复的
        /*定义一个专门的函数,专门用来 为指定的元素绑定单击响应函数
             1. 将重复的步骤 总结出来;
             2.变动的地方用参数传入;
                --2.1 idstr 单击响应函数对象的 id属性值
                --2.2 不同操作对象的 回调函数,当点击时候该函数触发;
        */
      
         function myclick(idstr,fun){
            var btn = document.getElementById(idstr);
            //为对象绑定动作
            btn.onclick = fun;
          };   
      
                // 7.为 id是 btn07的按钮 绑定一个单击响应函数         
         myclick("btn07",function(){
            //返回 #bj 的父节点
            var bj = document.getElementById("bj");
            var cns3 = bj.parentNode ;
            alert(cns3);//[object HTMLUListElement]
            //innerHTML和innerText 
            alert(cns3.innerHTML);
            alert(cns3.innerText);
        });
    
    
        // 8.为 id是 btn08的按钮 绑定一个单击响应函数  
        myclick("btn08",function(){
             //返回 #android 的前一个兄弟节点
            var and = document.getElementById("android");
            var cns8 = and.previousSibling;
            alert(cns8.innerHTML);
        });       
    
    
        // 9.为 id是 btn09的按钮 绑定一个单击响应函数  
        myclick("btn09",function(){
            //返回#username的value属性值
            var user = document.getElementById("username");
            alert(user.value);
        }); 
    
    
        // 10.为 id是 btn10的按钮 绑定一个单击响应函数  
        myclick("btn10",function(){
            //设置#username的value属性值
            var user = document.getElementById("username");
            user.value = "你好";
        }); 
    
    
        // 11.为 id是 btn11的按钮 绑定一个单击响应函数  
        myclick("btn11",function(){
            //返回 #bj 的文本值
            var bj = document.getElementById("bj");
            //alert(bj.innerText);//这种方式是通过获取id内部文本
            //var fir = bj.firstChild;//这种方式是 通过获取id第一个子节点的文本
            alert(bj.firstChild.nodeValue);
        }); 
    

    };//onload加载完毕

    
    - 对多选框`checkbox`的属性`.checked`可以设置选框的是否选中状态;
    - [x] `元素.checked = true;`        
    - [ ] `元素.checked = false;`
    ```javascript
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>全选练习</title>
        <script type="text/javascript">
            window.onload = function(){
    
                var checkedallbtn = document.getElementById("checkedallbtn");
                checkedallbtn.onclick = function(){
                     //1.checkedallbtn全选
                     var items = document.getElementsByName("items");
                     for(var i=0; i<items.length; i++){
                         items[i].checked = true;
                     }
                     //checkallbox全选/全不选框同步
                     checkallbox.checked = true;
                };
    
                var checkednobtn = document.getElementById("checkednobtn");
                checkednobtn.onclick = function(){
                     //2.checkednobtn
                     var items = document.getElementsByName("items");
                     for(var i=0; i<items.length; i++){
                         items[i].checked = false;
                     }
    
                      //checkallbox全选/全不选框同步
                     checkallbox.checked = false;
                };
    
    
                var checkedrevbtn = document.getElementById("checkedrevbtn");
                checkedrevbtn.onclick = function(){
                     //3.checkedrevbtn
                     var flag = 0;
                     var items = document.getElementsByName("items");
                     for(var i=0; i<items.length; i++){
    
                     items[i].checked = !items[i].checked ;
    
                     if(items[i].checked == false)
                            flag = 1;//若有未被选中的标记一下,总控制状态
                     }
    
                     if(flag == 0) checkallbox.checked = true;
                     else{
                        checkallbox.checked = false;
                        flag=0;
                     }
                };
    
                var sendbtn = document.getElementById("sendbtn");
                sendbtn.onclick = function(){
                     //4.sendbtn
                     var items = document.getElementsByName("items");
                     for(var i=0; i<items.length; i++){
    
                        if(items[i].checked == true)
                        //注意这 弹出的是多选框的value属性值
                         alert(items[i].value);                    
                     }
                };
    
    
    
                var checkallbox = document.getElementById("checkallbox");
                checkallbox.onclick = function(){
                    //5.checkallbox全选/全不选框
                    var items = document.getElementsByName("items");
                    for(var i=0; i<items.length; i++)
                    //下具体的四个多选框状态要与 总控制框 状态 一致,但是这个是总控制单方面的控制
                    //items[i].checked = checkallbox.checked;
                    //此处的 this 是以方法的形式传入,所以this代指的是对象checkallbox(响应事件中,响应函数是哪个主子绑定的,this就指代的是谁)
                    items[i].checked = this.checked; 
                };
    
                //细节:反过来,如果四个多选框全都选中,总控框也应该选中;
                // 如果四个多选框有没选中,总控框也应该取消全选;
                //需要给四个多选框 分别绑定点击相应函数 (每勾选一个框就要全部状态都判断一次)
                var items = document.getElementsByName("items");
    
                for(var i=0; i<items.length; i++){
                    items[i].onclick = function(){
    
                        checkallbox.checked = true;
                        //点击下每一个多选框的时候判断其余三个多选框的状态
                        for(var j=0; j<items.length; j++){
                            //有一个框没被选中,则总框也要取消全选
                            if(!items[j].checked) 
                            checkallbox.checked = false ;
                        }
    
                    };
                }
    
    
    
    
                //6.items
            };
        </script>
    </head>
    <body>
        <form method="post" action="">
            你爱好的运动是?
            <input type="checkbox" id="checkallbox">全选/全不选
            <br>
            <input type="checkbox" name="items" value="足球">足球
            <input type="checkbox" name="items" value="篮球">足球
            <input type="checkbox" name="items" value="羽毛球">羽毛球
            <input type="checkbox" name="items" value="乒乓球">乒乓球
            <br>
            <input type="button" id="checkedallbtn" value="全 选">
            <input type="button" id="checkednobtn" value="全不选">
            <input type="button" id="checkedrevbtn" value="反 选">
            <input type="button" id="sendbtn" value="提 交">
        </form>
    </body>
    </html>
    

    4. document对象的其他的属性和方法

    • document.all获取页面中的所有元素,相当于document.getElementsByTagName(“*”);
    • document.documentElement获取页面中html根元素
    • document.body获取页面中的body元素
    • document.getElementsByClassName()根据元素的class属性值查询一组元素节点对象;不支持IE8及以下的浏览器
    • **document.querySelector()**根据CSS选择器去页面中查询一个元素
      如果匹配到的元素有多个,则它会返回查询到的第一个元素
    • **document.querySelectorAll()**根据CSS选择器去页面中查询一组元素;会将匹配到所有元素封装到一个数组中返回,即使只匹配到一个

      var div = document.querySeletor(".box div");
      

      5. DOM增删改

    • document.createElement("TagName")可以用于创建一个元素节点对象,它需要一个标签名作为参数,将会根据该标签名创建元素节点对象,并将创建好的对象作为返回值返回;

    • document.createTextNode("textContent")可以根据文本内容创建一个文本节点对象
    • **父节点.appendChild(子节点)**向父节点中添加指定的子节点
    • **父节点.insertBefore(新节点,旧节点)** 将一个新的节点插入到旧节点的前边
    • 父节点.replaceChild(新节点,旧节点) 使用一个新的节点去替换旧节点
    • **父节点.removeChild(子节点)**删除指定的子节点
      有时候不知道父节点,则推荐方式:**子节点.parentNode.removeChild(子节点)**
    • 以上方法,实际就是改变了相应元素(标签)的innerHTML的值。 ```javascript <!DOCTYPE html>