JS 基础

一、简介

1、JavaScript

--JavaScript负责页面中的的行为。 ​ --它是一门运行在浏览器端的脚本语言。 ​ --JS的编写的位置 ​ 1.可以编写到标签的指定属性中 ​ <button onclick="alert('hello');">我是按钮</button><a href="javascript:alert('aaa');">超链接</a> ​ 2.可以编写到script标签中

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

3.可以将代码编写到外部的js文件中,然后通过标签将其引入

<span style="background-color:#f8f8f8"><span style="color:#333333">        <span style="color:#117700"><</span><span style="color:#117700">script</span> <span style="color:#0000cc">type</span>=<span style="color:#aa1111">"text/javascript"</span> <span style="color:#0000cc">src</span>=<span style="color:#aa1111">"文件路径"</span><span style="color:#117700">></</span><span style="color:#117700">script</span><span style="color:#117700">></span></span></span>

2、输出语句

--alert("要输出的内容"); ​ --该语句会在浏览器窗口中弹出一个警告框 ​ --document.write("要输出的内容"); ​ --该内容将会被写到body标签中,并在页面中显示 ​ --console.log("要输出的内容"); ​ --该内容会被写到开发者工具的控制台中

3、基本语法

1、注释:

--单行注释 //注释内容

--多行注释 /* 注释内容 */

2、JS严格区分大小写

3、JS中每条语句以分号(;)结尾

4、JS中会自动忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化。

4、字面量和变量

字面量:固定的值

变量:

--变量声明:使用var关键字来声明一个变量 var a;

--变量赋值:a = 1;

--同时声明和赋值:var a = 1;

5、标识符

在JS中所有的可以自主命名的内容,都可以认为是一个标识符,比如:变量名、函数名、属性名

--规范:

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

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

3.标识符不能是JS中的关键字和保留字

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

二、数据类型

JS中一共九种数据类型

其中基本类型:String(字符串) Number(数字) Boolean(布尔) Null(空) Undefined(未定义) Symbool

引用数据类型:Object(对象) Array(数组) Function(函数)

1、String

1、JS的字符串需要使用单引号或者双引号引起来

2、在字符串中使用\作为转义字符

<span style="background-color:#f8f8f8"><span style="color:#333333">\' ==> '
\" ==> "
\n ==> 换行
\t ==> 制表符
\\ ==> \</span></span>

使用typeof运算符检查字符串时,会返回string

2、Number

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

2、JS中可以表示的数字的最大值

Number.MAX_VALUE 1.7976931348623157e+308

表示大于0的最大值

Number.MIN_VALUE 5e-324

3、特殊的数字:

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

-Infinity 负无穷 使用typeof检查Infinity和-Infinity会返回number

NaN 是一个特殊的数字,表示非法数字(Not A Number) 使用typeof检查NaN也会 返回number

4、在JS中整数的运算基本可以保证精确

如果使用JS进行浮动计算,可能得到一个不精确的结果

3、Boolean

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

true 表示真

false 表示假

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

4、Null & Undefined

Null(空值)类型的值只有一个,就是null,专门用来表示一个为空的对象

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

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

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

使用typeof检查一个undefined值时,返回undefined

5、强制类型转换

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

类型转换主要指,将其他的数据类型转为string number boolean

1、将其他数据类型转换为string

方式一:

  • 调用被转换数据类型的toString()方法
  • 该方法不会影响到原变量,它会将转换的结果返回
  • 但是null和undefined这两个值没有toString()方法

方式二:

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

对于number和boolean实际上就是调用toString()方法

对于null和undefined,不会调用toString()

会将null直接转换为"null"

会将undefined直接转换为"undefined"

2、将其他数据类型转换为Number

方式一:

--使用Number()函数

(1)字符串 --> 数字

1、如果是纯数字。直接将其转换为数字

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

3、如果字符串是一个空串,则转换为0

(2)布尔 --> 数字

true 转为1

false 转为0

(3)null --> 数字 0

(4)undefined --> 数字 NaN

方式二:(这种方式专门对付字符串)

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

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

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

在JS中,如果需要表示16进制数,则需要以0x开头

如果需要表示8进制数,需要以0开头

如果需要表示2进制数,需要以0b开头

但不是所有浏览器都支持

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

对于Number调用toString()时可以在方法中传递一个整数作为参数,此时它将会把数字转换为指定类型,如果不指定默认转换为10进制

3、将其他数据类型转换为Boolean

方式一:

使用Booalean()函数

(1)数字 --> 布尔

除了0和NaN,其余都是true

(2)字符串 --> 布尔

除了空串,其余都是true

(3)null和undefined都会转化为flase

(4)对象也会转化为true

4、隐式转换

1、为任意的数据类型+一个"",即可将其转换为String

2、任意值做-0 *1 /1运算可将其转换为Number

对一个其他的数据类型使用+,来将其转换为number

3、为一个任意数据类型取两次反,来将其转换为Boolean

三、运算符

运算符也叫操作符,通过运算符可以对一个或多个值进行计算,并获取运算结果

1、算术运算符

--当对非number类型的值进行计算时,会将这些值转化为Number然后再运算

--任何值和NaN做运算逗得NaN

(1)+

可以对两个值进行加法运算,并将结果返回

任何值和字符串做加法运算,都会先转换为字符串,然后和字符串做拼接

我们可以利用这一特点,只需要为任意的数据类型+一个"",即可将其转换为String

(2)- * / %

任意值做-0 *1 /1运算可将其转换为Number

2、一元运算符

+正号 正号不会对数字产生影响

-负号 负号对数字进行负号的取反

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

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

3、自增和自减

自增++

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

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

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

自减--

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

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

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

4、逻辑运算符

!非 &&与 ||或

1、!非

非运算就是对一个数据进行取反,true变false,false变true,最后返回的一定是个Boolean

如果对一个值进行两次取反,则不会发生变化

可以利用该特点,来将一个其他的数据类型转换为布尔值,可以为一个任意数据类型取两次反,来将其转换为布尔值

涉及到布尔判定

2、&&与

运算规则:

两个值中只要有一个值为false就返回false,只有两个值都为true时,才会返回true

--JS中的“或”属于短路的与,如果第一个值为false,则不会检查第二个值

3、||或

运算规则:

两个值中只要有一个true,就返回true,如果两个值都为false,才返回false

--JS中的“或”属于短路的或,如果第一个值为true,则不会检查第二个值

4、非布尔值情况

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

--与运算

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

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

--或运算

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

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

5、赋值运算符

= += -= *= /=

a+=5 ==》 a = a+5

6、关系运算符

通过关系运算符比较两个值之间的大小关系,如果关系成立返回true,不成立则返回false

< <= > >=

非数值的情况:

对于非数值进行比较,会将其转换为数字然后再比较

任何值和NaN比较都是false

如果符号两侧的值都是字符串,不会将其转换为数字,而会分别比较字符串字符的Unicode编码

任比较字符编码时是一位一位进行比较,如果两位一样,则比较下一位

在比较两个字符串型的数字时,一定要转型

7、Unicode编码

在字符串中:\u四位编码

在网页中:&#编码;这里编码需要10进制

8、相等运算符

如果相等会返回true,否则返回false

1、相等==

--相等返回true,不相等返回flase

--如果值的类型不同,会自动进行类型转换,将其转换为相同得类型,然后再比较

undefined衍生自null,所以两个值做相等判断,会返回true

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

可以通过isNaN()函数来判断一个值是否是NaN,如果该值是NaN则返回true

不相等!=

--不相等返回true,否则返回false

--如果值的类型不同,会自动进行类型转换,将其转换为相同得类型,然后再比较

2、全等===

--用来判断两个值是否全等,与相等类似,但是不会进行类型转换

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

不全等!==

--用来判断两个值是否不全等,和不等类似,但是不进行类型转换

--如果两个值类型不同,直接返回true

9、条件运算符

条件运算符也叫三元运算符

语法:

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

流程:

首先对条件表达式进行求值,如果该值为true,则执行语句1,并返回执行结果

如果该值为false,则执行语句2,并返回执行结果

--如果条件的表达式的求值结果是一个非布尔值,会将其转换为布尔值,再进行计算

四、流程控制语句

语句的分类:

1、条件判断语句

2、条件分支语句

3、循环语句

1、条件判断语句

if语句

语法一: if(条件表达式){ 语句... }

语法二: if(条件表达式1){ 语句1 }else if(条件表达式2){ 语句2 }else if(条件表达式3){ 语句3 }else{ 语句4 }

该语句只有一个代码块会被执行,一旦代码块执行,则直接结束语句

2、条件分支语句

switch语句

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

在执行时会依次将case后的表达式的值和switch后的条件表达式的值进行全等比较,如果比较结果为true,则从当前case处开始执行代码。

3、循环语句

通过循环语句可以反复的执行一段代码多次

1、while循环

语法:

while(条件表达式){ ​ 语句... ​ }

流程:

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

如果值为true,则执行循环体,

循环体执行完毕后,继续对表达式进行判断,

如果为true,则继续执行循环体,

如果为false,则终止循环

2、do...while循环

语法:

do{

语句...

}while(条件表达式)

流程:

先执行循环体

循环体执行完毕后,对while后的条件表达式进行判断,

如果结果为true,则继续执行循环体,执行完毕继续判断

如果结果为false,则终止循环

do...while可以保证循环至少执行一次

3、for循环

语法:

for(①初始化表达式;②条件表达式;④更新表达式{ ​ ③语句... ​ }

流程:

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

②执行条件表达式,判断是否执行循环。

如果为true,则执行循环③

如果为false,终止循环

④执行更新表达式,更新表达式执行完毕继续重复②

4、break和continue

1、break

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

不能在if语句中使用break和continue

break关键字,会立即终止离他最近的那个循环语句

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

--label:循环语句

break label

这样break将会结束指定的循环,而不是最近的

2、continue

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

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

五、对象(Object)

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

1、对象的分类:

1、内建对象:

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

--例如:Math String Nuber Function Object

2、宿主对象:

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

--比如:BOM DOM

3、自定义对象

2、对象使用

1、 创建对象

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

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

使用typeof检查一个对象时,会返回object

var obj = new Object();

2、

在对象中保存的值称为属性

向对象添加属性

语法:对象.属性名 = 属性值;

3、

读取对象中的属性

语法:对象.属性名

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

4、

修改对象的属性值

语法:对象.属性名 = 新值

5、

删除对象的属性

语法:delete 对象.属性名

3、属性名和属性值

(1)属性名

对象的属性名不强制要求遵守标识符的规范,但是我们使用是还是尽量按照标识符的规范去做

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

需要使用另一种方式

语法:对象["属性名"] = 属性值

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

在[]中可以直接传递一个变量,这样变量值是多少就会读取那个属性

(2)属性值

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

(3)in 运算符

--通过该运算符可以检查一个对象中是否含有指定的属性

如果有则返回true,没有则返回false

原型中有,也会返回true

语法:

"属性名" in 对象

4、基本数据类型和引用数据类型

JS中的变量都是保存到栈内存中的

基本数据类型的值直接在栈内存中存储

值与值之间是独立存在,修改一个变量不会影响其他的变量

对象是保存到堆内存中的,每创建一个新的对象,就会在堆内存中开辟出一个新的空间

而变量保存的是对象的内存地址(对象的引用),如果两个变量保存的是同一个对象引用,当一个通过一个变量修改属性时,另一个也会受到影响

所以:

当比较两个基本数据类型的值时,就是比较值。

而比较两个引用数据类型时,它是比较的对象的内存地址,

如果两个对象是一模一样的,但是地址不同,它也会返回false

5、对象字面量

使用对象字面量来创建一个对象

语法:

var 对象 = {属性名:属性值,属性名:属性值....}

对象字面量的属性名可以加引号也可以不加,建议不加

属性名和属性值是一组一组的名值对结构: 名和值之间使用:连接,多个名值对之间使用,隔开

6、枚举对象中的属性

使用for ... in 语句

语法:

for(var 变量 in 对象){

***

}

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

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

查看obj对象的属性和属性值

for(var n in obj){

console.log("属性名:"+n);

console.log("属性值:"+obj[n]);

}

7、包装类

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

String() Boolean() Number()

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

当我们去操作一个基本数据类型的属性和方法时,

解析器会临时将其转换为对应的包装类,然后再去操作属性和方法,

操作完成以后再将这个临时对象进行销毁。

六、函数(Function)

1、创建函数

1、使用 函数声明 来创建一个函数

语法:

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

语句...

}

2、使用 函数表达式 来创建一个函数

语法:

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

语句....

}

3、调用函数

函数对象()

2、函数的参数

可以在函数的()中来指定一个或多个形参(形式参数)

多个形参之间使用,隔开,声明形参就相当于在函数内部声明了对应的变量

但是并不赋值

在调用函数时,可以在()中指定实参(实际参数)

实参将会赋值给函数中对应的形参

**

1、调用函数时解析器不会检查实参的类型,

所以要注意,是否有可能会接收到非法的参数,如果有可能则需要对参数进行类型的检查

函数的实参可以是任意的数据类型,也可以是一个对象

2、调用函数时,解析器也不会检查实参的数量

多余实参不会被赋值

如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined

3、返回值

可以使用 return 来设置函数的返回值

语法:

return 值

返回值可以是任意的数据类型,也可以是一个对象,也可以是一个函数

return后的值将会会作为函数的执行结果返回,可以定义一个变量,来接收该结果

在函数中return后的语句都不会执行

如果return语句后不跟任何值就相当于返回一个undefined,

如果函数中不写return,则也会返回undefined

4、立即执行函数

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

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

(function(){

alert("我是一个匿名函数");

})();

立即执行函数可以避免全局污染,改变全局变量和全局函数的作用域

5、 方法

函数也可以成为对象的属性,

如果一个函数作为一个对象的属性保存,那么我们称这个函数是这个对象的方法

调用这个函数就说调用对象的方法(method)

var obj = {

name:“猪八戒”;

age:18;

sayname:function(){

console.log(obj.name);

}

}

obj.sayname() 叫做调用obj的sayname方法

6、作用域和声明提前

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

1、全局作用域

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

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

--在全局作用域中有一个全局对象window,它代表的是一个浏览器的窗口,它由浏览器创建我们可以直接使用

--在全局作用域中:

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

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

--全局作用域中的变量都是全局变量,在页面的任意的部分都可以访问的到

2、声明提前

(1)变量的声明提前

使用var关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值),

但是如果声明变量时不适用var关键字,则变量不会被声明提前

(2)函数的声明提前

使用函数声明形式创建的函数 function 函数(){},它会在所有的代码执行之前就被创建,所以我们可以在函数声明前来调用函数

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

3、函数作用域

--调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁

--每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的

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

在全局作用域中无法访问到函数作用域的变量

--当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用

如果没有则向上一级作用域中寻找,直到找到全局作用域,

如果全局作用域中依然没有找到,则会报错ReferenceError

--在函数中要访问全局变量可以使用window对象

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

//内部作用域能访问的外部,取决于函数定义的位置,和调用位置无关

7、预编译

函数调用时先进行预编译(过程):

1、创建AO对象

2、找形参和变量声明,将变量声明和形参作为AO属性名,值为undefined

3、将实参值和形参统一

4、在函数体里面找到函数声明,值为函数体

全局预编译:

1、创建GO对象

2、找变量声明,将变量声明作为GO属性名,值为undefined

3、找函数声明,放入GO

预编译完成后,会按照代码顺序执行

一段代码,先创建GO,再创建AO。如果函数体里的变量在AO中有,则取AO中的,如果没有,去找GO中的,从近到远的找。

<span style="background-color:#f8f8f8"><span style="color:#333333">补充:
任何变量,如果未经声明就赋值,其变量为全局变量所有;
一切声明的全局变量,全是 window 的属性(window 即为 GO)</span></span>

8、this

  • 在全局代码中使用this,指代全局对象

    在真实的开发中,很少在全局代码使用this

  • 在函数中使用this,它的指向完全取决于函数是如何被调用的

    调用方式示例函数中的this指向
    通过new调用new method()新对象
    直接调用method()全局对象
    通过对象调用obj.method()前面的对象
    callmethod.call(ctx)call的第一个参数
    applymethod.apply(ctx)apply的第一个参数

9、构造函数

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

语法:

function 函数名(大驼峰式)(){

语句

}

var 对象名 = new 函数名()

构造函数和普通函数的区别就是调用方式的不同

普通函数是直接调用,而构造函数需要使用new关键字来调用

--构造函数的内部原理:

1、在函数体最前面隐式的加上this={}

2、执行this.xxx=xxx(给this这个对象添加属性名和属性值)

3、隐式的返回this(return this)

使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类

将通过一个构造函数创建的对象,称为是该类的实例

10、静态成员和实例成员

<span style="background-color:#f8f8f8"><span style="color:#333333"><span style="color:#aa5500">// 构造函数</span>
<span style="color:#770088">function</span> <span style="color:#0000ff">Person</span>(<span style="color:#0000ff">name</span>, <span style="color:#0000ff">age</span>){
    <span style="color:#770088">this</span>.<span style="color:#000000">name</span> <span style="color:#981a1a">=</span> <span style="color:#0055aa">name</span>; <span style="color:#aa5500">// 实例属性</span>
    <span style="color:#770088">this</span>.<span style="color:#000000">age</span> <span style="color:#981a1a">=</span> <span style="color:#0055aa">age</span>; <span style="color:#aa5500">// 实例属性 </span>
}
<span style="color:#aa5500">// 实例方法</span>
<span style="color:#aa5500">// 对于每一个实例对象来讲,实例属性值不一样</span>
<span style="color:#aa5500">// 但是实例方法是一样的,所以我们就选择挂在原型上面</span>
<span style="color:#000000">Person</span>.<span style="color:#000000">prototype</span>.<span style="color:#000000">sayHello</span> <span style="color:#981a1a">=</span> <span style="color:#770088">function</span>(){
    <span style="color:#aa5500">//...</span>
}
<span style="color:#000000">Person</span>.<span style="color:#000000">test</span> <span style="color:#981a1a">=</span> <span style="color:#116644">1</span>;
​
<span style="color:#770088">var</span> <span style="color:#0000ff">xiejie</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">Person</span>(<span style="color:#aa1111">"谢杰"</span>, <span style="color:#116644">18</span>);
<span style="color:#770088">var</span> <span style="color:#0000ff">qiu</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">Person</span>(<span style="color:#aa1111">"秋"</span>, <span style="color:#116644">19</span>);
<span style="color:#aa5500">// 这里的 xiejie 和 qiu 就是实例对象</span>
<span style="color:#aa5500">// 我们把 new 这个过程称之为实例化</span>
​
<span style="color:#770088">var</span> <span style="color:#0000ff">sc</span> <span style="color:#981a1a">=</span> <span style="color:#770088">new</span> <span style="color:#000000">Person</span>(<span style="color:#aa1111">"SC"</span>, <span style="color:#116644">18</span>);
<span style="color:#000000">console</span>.<span style="color:#000000">log</span>(<span style="color:#000000">xiejie</span>.<span style="color:#000000">name</span>);
<span style="color:#000000">console</span>.<span style="color:#000000">log</span>(<span style="color:#000000">xiejie</span>.<span style="color:#000000">age</span>);
<span style="color:#000000">xiejie</span>.<span style="color:#000000">sayHello</span>();
<span style="color:#aa5500">// 无论是实例属性,还是实例方法,我们都称之为实例成员</span>
<span style="color:#aa5500">// this.xxx,xxx就是实例成员</span>
<span style="color:#aa5500">// 实例成员只能通过实例对象来访问</span>
<span style="color:#aa5500">// 静态成员呢?静态成员是挂在类(构造函数)上面的,不需要实例化,直接通过类(构造函数)来调用</span>
<span style="color:#aa5500">// 静态成员其实你们早就见过</span>
<span style="color:#aa5500">// Math.random();</span>
​
<span style="color:#000000">console</span>.<span style="color:#000000">log</span>(<span style="color:#000000">Person</span>.<span style="color:#000000">test</span>); <span style="color:#aa5500">// test 就是一个静态成员</span>
​</span></span>

11、原型(prototype)

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

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

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

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

原型对象就相当于一个公共的区域,凡是通过同一个构造函数创建的对象他们通常都可以访问到相同的原型对象。我们可以将对象中共有的属性和方法统一添加到原型对象中,这样我们只需要添加一次,就可以使所有的对象都可以使用。

当我们去访问对象的一个属性或调用对象的一个方法时,它会先自身中寻找,

如果在自身中找到了,则直接使用。

如果没有找到,则去原型对象中寻找,如果找到了则使用,

如果没有找到,则去原型的原型中寻找,依此类推。直到找到Object的原型为止,Object的原型的原型为null,

如果依然没有找到则返回undefined

--hasOwnProperty() (boolean)

这个方法可以用来检查对象自身中是否含有某个属性,不包含原型中的属性

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

--“属性名” in 对象 (boolean)

这个方法也是用来检查对象中是否含有某个属性,但是包含原型中的属性

12、原型链

image-20210903152359095

13、call和apply

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

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

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

--arguments

arguments和this类似,都是函数中的隐含的参数

arguments是一个类数组元素,它用来封装函数执行过程中的实参,所以即使不定义形参,也可以通过arguments来使用实参

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

七、数组(Array)

1、数组

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

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

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

索引指由0开始的整数

数组的操作:

(1)创建数组:

var arr = new Array();

var arr = [];

(2)向数组中添加元素:

数组对象[索引] = 值;

(3)创建数组时直接添加元素

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

(4)获取和修改数组的长度

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

--获取长度:

数组.length

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

--修改数组的长度

数组.length = 新长度

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

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

--向数组的最后添加元素

数组[数组.length] = 值;

2、数组的方法

1、push()

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

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

2、pop()

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

3、unshift()

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

4、shift()

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

5、slice()

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

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

--参数

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

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

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

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

6、splice()

可以用来删除数组中指定元素,并使用新的元素替换

该方法会影响到原数组,会将指定元素从原数组中删除,并将删除的元素封装到新数组中返回

--参数

1.删除开始位置的索引

2.删除的个数

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

将伪数组变为真数组:Array.prototype.slice.call(obj)

7、reverse()

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

8、concat()

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

9、join()

可以将一个数组转换为一个字符串

--参数

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

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

10、sort()

可以对一个数组中的内容进行排序,默认是按照Unicode编码进行排序

调用以后,会直接修改原数组。

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

数组名.sort(function(a,b){

return a-b; 升序排列

return b-a; 降序排列

})

3、遍历数组

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

for(var i=0 ; i<数组.length ; i++){ //数组[i] }

2、使用forEach()方法来遍历数组(不兼容IE8)

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

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

数组中有几个元素,回调函数就会被调用几次

每次调用时,都会将遍历到的信息以实参的形式传递进来,我们可以定义形参来获取这些信息。

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

value:正在遍历的元素

index:正在遍历元素的索引

obj:被遍历对象

八、DOM

Document Object Model

文档对象模型,通过DOM可以来任意来修改网页中各个内容

1、介绍

--文档:文档指的是网页,一个网页就是一个文档

--对象:对象指将网页中的每一个节点都转换为对象,转换完对象以后,就可以以一种纯面向对象的形式来操作网页了

--模型:模型用来表示节点和节点之间的关系,方便操作页面

--节点(Node):

节点是构成网页的最基本的单元,网页中的每一个部分都可以称为是一个节点

常用的节点:

文档节点 (Document),代表整个网页

元素节点(Element),代表网页中的标签

属性节点(Attribute),代表标签中的属性

文本节点(Text),代表网页中的文本内容

2、DOM操作

DOM查询

在网页中浏览器已经为我们提供了document对象,

它代表的是整个网页,它是window对象的属性,可以在页面中直接使用

document查询方法:

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

document.getElementById("id属性值");

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

document.getElementsByName("name属性值");

根据标签名来查询一组元素节点对象:

document.getElementsByTagName("标签名");

元素的属性:

(1)读取元素的属性:元素.属性名

(2) 修改元素的属性:元素.属性名 = 属性值

(3)innerHTML: 使用该属性可以获取或设置元素内部的HTML代码

3、事件(Event)

事件指的是用户和浏览器之间的交互行为。比如:点击按钮、关闭窗口、鼠标移动...

我们可以为事件来绑定回调函数来响应事件。

绑定事件的方式:

1.可以在标签的事件属性中设置相应的JS代码

<button onclick="js代码。。。">按钮</button>

但是这种写法我们称为结构和行为耦合,不方便维护,不推荐使用

2.可以通过为对象的指定事件属性设置回调函数的形式来处理事件

<span style="background-color:#f8f8f8"><span style="color:#333333"><button id="btn">按钮</button>
<script>
    //获取按钮对象
    var btn = document.getElementById("btn");
    //为按钮的对应事件绑定处理函数的形式来响应事件
    btn.onclick = function(){
                        
                        };
</script></span></span>

4、文档的加载

浏览器在加载一个页面时,是按照自上向下的顺序加载的,加载一行执行一行。

如果将js代码编写到页面的上边,当代码执行时,页面中的DOM对象还没有加载,此时将会无法正常获取到DOM对象,导致DOM操作失败。

解决方式一:

可以将js代码编写到body的下边

<span style="background-color:#f8f8f8"><span style="color:#333333"><button id="btn">按钮</button>
<script>
    //获取按钮对象
    var btn = document.getElementById("btn");
    //为按钮的对应事件绑定处理函数的形式来响应事件
    btn.onclick = function(){
                        
                        };
</script></span></span>

解决方式二:

将js代码编写到window.onload = function(){}中

--window.onload 对应的回调函数会在整个页面加载完毕以后才执行,所以可以确保代码执行时,DOM对象已经加载完毕了

<span style="background-color:#f8f8f8"><span style="color:#333333"><script>
    window.onload = function(){
           var btn = document.getElementById("btn");
           btn.onclick = function(){
                    
            };
    };
            
</script>   </span></span>

5、DOM的其他方法

,修改;对CSS的操作

  1. 获取body元素:document.body

  2. 获取html元素:document.documentElement

  3. 获取页面中的所有元素:document.all

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

    getElementByClassName() 但是该方法不支持IE8及以下的浏览器

  5. document.querySelector()和document.querySelectorAll()

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

    区别:

    document.querySelector()总会返回唯一的一个元素,如果满足条件的元素有多个,那么他只会返回第一个

    document.querySelectorAll()会将符合条件的元素封装到一个数组中返回

6、DOM的增删改方法

  1. 创建元素节点

    document.createElement()

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

  2. 创建文本节点

    document.createTextNode()

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

  3. 向父元素中添加子节点

    语法:父元素.appendChild(子节点)

    其中向元素节点中添加文本节点,可以用:元素.innerHtml = "文本"

  4. 指定子节点前插入新的子节点

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

  5. 指定子节点替换已有子节点

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

  6. 删除子节点

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

    子节点.parentNode.removeChild(子节点)(这种用法可以不用知道父节点)

九、事件(event)

1、事件对象:

当响应函数被调用时,浏览器每次都会将一个事件对象作为实参传递进响应函数中,这个事件对象中封装了当前事件的相关信息,比如:鼠标的坐标,键盘的按键,鼠标的按键,滚轮的方向。。

可以在响应函数中定义一个形参,来使用事件对象,但是在IE8以下浏览器中事件对象没有做完实参传递,而是作为window对象的属性保存

元素.事件 = function(event){ event = event || window.event; }

2、事件的冒泡(Bubble)

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

--事件的冒泡大部分情况下都是有益的,如果需要取消冒泡,则需要使用事件对象来取消

--可以将事件对象的cancelBubble设置为true,即可取消冒泡

元素.事件 = function(event){ event = event || window.event; event.cancelBubble = true; };

3、事件的委派

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

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

4、事件的绑定

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

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

2、addEventlistener()

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

参数:

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

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

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

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

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

3、attachEvent()

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

参数:

1.事件的字符串,要on

2.回调函数

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

4、自定义函数

参数:

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);

});

}

}

5、事件的传播

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

微软公司认为事件应该是由内向外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就说事件应该在冒泡阶段执行。

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

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

  • 1.捕获阶段

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

  • 2.目标阶段

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

  • 3.冒泡阶段

    事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件

如果希望在捕获阶段就触发事件,可以将addEventListener()的第三个参数设置为true

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

补充

1、测试程序的性能

1、计时器

在程序执行前,开启计时器

console.time("计时器的名字")

终止计时器

console.timeEnd("计时器名字")

2、时间戳

var start = Date.now();

程序

var end = Date.now();

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

2、生成随机数

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

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

3、判断元素是不是原始值

1、typeof

但是判断array和null会返回object

*typeof一个未定义的变量,不会报错,会返回字符串的undefined

2、instanceof

3、constructor

4、定时器

setTimeout和setInterval都属于JS中的定时器,可以规定延迟时间再执行某个操作。

但是setTimeout在规定时间后执行完某个操作就停止了;

而setInterval则可以一直循环下去。

5、布尔判定

所有需要判断真假的地方都会使用下面的规则

数据判定
false null undefined 0 NaN ''false
剩余所有数据true

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值