第一部分 基础

JavaScript Day01 课堂笔记

1 JS 的基本语法

1.1 JavaScript 在 HTML 中的书写方式

① 行内式
<button onclick="code..."></button>

依赖于事件

无法做到结构与行为分离

② 内嵌式
<script>
	code...
</script>

通常 JS 代码放在其他 html 标签的后面(js会阻塞html的加载)

案例练习的时候比较常用这种

③ 外链式
<script src="js文件的地址"></script>

与内嵌式一样,写在其他html标签的后面

外链式与内嵌式不要共用一 个 script 标签

实际开发中推荐这种方式

1.2 指令结束符

JavaScript 代码是由一条一条的指令(也叫语句)组成的,每条指定要有结束符。

结束符可以是 分号 ,也可以是 换行

1.3 内容输出

alert(内容)   // 弹框输出

console.log(内容)   // 控制台输出 (推荐,用于代码调试)

document.write(内容)  // 把内容输出到视口

1.4 JS 调试

F12 可以打开调试工具(开发者工具)

选择 console (控制台)

如果代码语法错误,控制台会输出红色的报错!!!

2 变量

2.1 变量和直接量

  • 计算机操作的都是数据,JavaScript 处理的都是数据。
  • 数据如果直接使用,称之为直接量
  • 给数据取个名字,使用数据的时候通过名字来用,这就是变量

2.2 声明一个变量

var 变量名 = 值; 标准写法。

var 变量名; 声明变量的时候不给值,声明完成后再给值。

var 变量1=值,变量2=值,变量3=值; 同时声明多个变量。

**注意:**变量的值可以修改!

var 关键字只有在声明变量的时候才会去使用。

2.3 变量名的命名规范

变量名由数字、字母、下划线、$ 组成且不能以数字开头。
变量名严格区分大小写。
变量名不能是保留字和关键字。(关键字就是在js中具有特殊意义的词)
变量名取得有意义,尽量使用英文,拼音也可以,不要混用。
变量名如果由多个单词组成,推荐使用小驼峰命名法, userName, userNameAge

3 数据类型

3.1 数据类型分类

原始类型:
	number    数值类型
	string     字符串
	boolean    布尔值
	null       空类型
	undefined  未定义类型


对象类型:
	array
	object
	function
	regexp
	date
	math
	.....

3.2 Number 类型

① 整型 int
十进制表示   100
八进制表示   011
十六进制表示  0x1f

② 浮点型 float
直接写小数  10.23
科学计数法  2.3e3  34e20
存在精度问题(因为所以的计算要转为二进制之后才能计算,大部分十进制的小数转为二进制小数的时候,不能精确)

③ 数值的范围
如果数值超出了范围,会显示为 Infinite -Infinite

④ 特殊的 number 值 NaN(Not a number)
NaN 类型是 number
特点:
NaN与任何数进行任何运算,结果仍然是NaN
NaN与任何数都不相等,包括自己。

⑤ 相关的函数
isFinite() 判断该数值是否超出范围,没超出范围返回 true,超出范围返回 false
isNaN()  判断该数值是否是 NaN,如果是NaN返回true,不是返回false

3.3 string 字符串

① 定义字符串
定义字符串可以使用 单引号 也可以使用双引号。
单引号和双引号没有任何区别。
单引号不能嵌套单引号;双引号不能嵌套双引号。
如果非要嵌套,可以对引号进行转义, \'   \"
② 转义字符

一些特殊功能的符号,可以用转义字符来表示。

\n  换行符
\t  水平制表符 Tab
\r  回车符
\'  对单引号进行转义
\"  对双引号进行转义
\\  对转义符本身进行转义
\uxxxx Unicode 编码
③ 字符串连接符
+

3.3 boolean 布尔值

true  表示真、确定、正确...
false 表示假、否定、错误...

3.4 null 和 undefined

null:
 	表示此处不应该有值。
 	1) 作为函数的参数,表示该函数的参数不是对象。
    2) 作为对象原型链的终点。
    3) 获取 DOM 获取不到的时候。

undefined:
	表示此处应该有值,但是没有定义。
	1)定义了变量没有给值,显示 undefined。
    2)定义了形参,没有传实参,显示 undefined。
    3)对象属性名不存在时,显示 undefined。
    4)函数没有写返回值,即没有写return,拿到的是 undefined。
    5)写了return,但没有赋值,拿到的是 undefined。

4 数据类型转换

4.1 强制类型转换(显示类型转换)

① 转换函数
把其他类型数据转为 number 类型:
Number()
parseInt()
parseFloat()

把其他类型的数据转为 stirng 类型:
String()

把其他类型的数据转为 boolean 类型:
Boolean();
② 其他类型转为 number
使用 Number() 函数进行强制转换:
	string->number: 纯数字字符串转为对应的数字,空字符串转为0,其他的转为 NaN。
	boolean->number: true 转为 1,false 转为 0。
	undefined->number: nudefined 转为 NaN。
	null->number:null 转为 0。
	
parseInt()/parseFloat() 
	这两个函数的意思是从字符串中提取数字。所以,布尔值、null和undefined 都转为 NaN。
	空字符串转为NaN,因为空字符中提取不到数字。
	纯数字字符串和以数字开头的字符串,可以提取到数字;其他的字符都提取不到数字,转为NaN。
	parseInt 只取整数,parsetFloat 可以保留小数。
	特殊情况:
		十六进制表示的纯数字字符串,parseInt得到本来大小的整数,parsetFloat只能提取到 0。
		科学计算法表示的纯数字字符串,parsetFloat得到所表示的本来大小,parsetInt 只能提取到小数点前面的
③ 其他类型的数据转为字符串
使用 String() 函数强制转换
转换规则: 数据长什么样转为字符串就转为什么样
④ 其他类型的数据转为 boolean
0、NaN、空字符串、undefined、null 会转为 false
其他的都转为 true

4.2 自动类型转换(隐式类型转换)

JavaScript 是弱类型的语言,数据类型可以自动转换。

当一个数据处在某种运算环境下的时候,会自动转为该运算环境需要的数据类型。

number 的运算环境:进行 +、-、*、/、%、++、-- 等运算的时候。

string 的运算环境:+ 的一侧是字符串,另一侧的数据会自动转为字符串,进行字符串连接。

boolean 的运算环境:进行判断的时候,比如 if,其他类型的数据会自动转为 boolean。

自动类型转换的规则和强制类型转换(Number()、String()、Boolean())的规则是一样的。

5 运算符

5.1 运算符和表达式

① 运算符
像 + - * / % 这种进行运算的符号
与运算符一起组合的变量或者直接量称之为 操作数
② 表达式
表达式是由变量或直接量与运算符组成的式子,表达式有一个计算结果,称之为表达式的值。
最简单的表达式称之为“原始表达式”,如一个变量、一个直接量。
运算符可以把简单的表达式组合成复杂的表达式。
有些表达式有副作用,所谓副作用指的是,表达式在计算之后会对参与计算的变量进行影响。

5.2 运算符的分类

① 按照操作数的个数
一元运算符 一目运算符
二元运算符 二目运算符
三元运算符 三目运算符
② 按照运算符的功能
算术运算符
比较运算符
赋值运算符
逻辑运算符
位运算符
其他运算符

6 运算符详解

6.1 算术运算符

+   加法运算符、正号运算符
-   减法运算符、负号运算符
*   乘法运算符
/   除法运算符
%   取余(取模)运算符
++  递增运算符
--  递减运算符
递增运算符和递减运算符,具有副作用的运算符
变量 ++ : 表达式取变量没有递增前的值作为表达式的值;先取值后递增。
++ 变量 : 表达式取变量递增之后的值作为表达式的值;先递增后取值。
变量 -- 和 -- 变量 同理

副作用:对变量的影响,是不在乎 ++/-- 在前还是在后的。

6.2 关系运算符

==  相等运算符
!=  不相等运算符
=== 全等运算符
!== 不全等运算符
>  大于
<  小于
>= 大于等于
<= 小于等于

== 判等规则:

① 先看两边的类型是否一致,如果一致,就看值是不是相同。

② 如果类型不一致,会进行自动类型转换,转为 number 类型,再进行比较。

③ 遇到 null, 有特殊情况

​ null 和 undefined 相等

​ null 和 0 不等

​ null 和 空字符串 不等

​ null 和 false 不等

=== 判等规则:

先看两边的操作数数据类型是否一致,如果不一致,直接返回 false,

如果类型一致,再去比较值是否相等。

推荐使用 ===

字符串可以比较大小:

用每个字符对应的 ascii 码值(ascii码值是数字)进行比较。

字符串的比较是一位一位的进行比较,比出大小之后,后面的字符就不比了。

关系运算符所组成的表达式的值是布尔值

6.3 逻辑运算符

&&  逻辑与 两边的条件都满足整体才满足。
    逻辑与运算符组成的表达式的值是两边的操作数中的一个:
    ① 如果左边的操作数成立,直接把右边操作数的值作为整个表达式的值;
    ② 如果左边的操作数不成立,直接把左边操作数的值作为整个表达式的值,右边的不看了。


||  逻辑或 两边的条件满足一个,整体就满足。
	逻辑或运算符组成的表达式的值是两边的操作数中的一个:
	① 如果左边的操作数成立,直接把左边操作数的值作为整个表达式的值,右边的不看了。
	② 如果左边的操作数不成立,把右边操作数的值作为整个表达式的值。


!   逻辑非 进行取反操作,如果操作数不是布尔值会转为布尔值,转了之后再取反;  逻辑非组成的表达式的值一定是布尔值

6.4 位运算符 (了解)

&  按位与
|  按位或
~  按位非
^  按位异或
>> 右移
<< 左移

6.1 赋值运算符

=
+=
-=
/=
*=
%=

6.2 其他运算符

?:  条件运算符(三元运算符)
   操作数1 ? 操作数2 : 操作数3   
   如果操作数1是成立的,取操作数2的值作为整个表达式的值,否则取操作数3的值作为整个表达式的值
   
typeof   判断类型,与typeof() 函数功能一致; 用法 typeof 操作数

, 运算符   用法:同时声明多个变量

6.3 运算符优先级

一元运算符 > 算术运算符(乘除>加减) > 比较大小 > 判等  > 逻辑与逻辑或 > ?: > 赋值运算符

7 分支结构

① 单向分支
if (条件表达式) {
	语句1;
	语句2;
	....
}
② 双向分支
if (条件表达式) {
	语句1;
	语句2;
	....
} else {
	语句1;
	语句2;
	....
}
③ 多向分支 else if
if (条件表达式) {
	语句1;
	语句2;
	....
} else if (条件表达式) {
	语句1;
	语句2;
	....
} else if (条件表达式) {
	语句1;
	语句2;
	....
} else {
	语句1;
	语句2;
	....
}
④ 多向分支 switch case
switch (表达式) {
	case 表达式可能的值:语句; break;
	case 表达式可能的值:语句; break;
	case 表达式可能的值:语句; break;
	case 表达式可能的值:语句; break;
	case 表达式可能的值:语句; break;
	default: 语句;
}

break 作用:

当某个 case 满足的时候,进行里面的语句,遇到 break 结束;要是没有 break 会继续向后执行,知道遇到 break

switch case 和 else if:

  1. swith case 适合某个表达式不同的值有不同的操作,这种情况;

​ 适合 else if 的情况用 switch case 不太简单。

2)else if 适合表达式的值,不同的取值范围有不同的操作;

​ 适合 switch case 的情况用 else if 也没有问题。

⑤ 嵌套分支(巢状分支)
if (条件表达式) {
	语句1;
	if (条件表达式) {
		语句;
	}
} else {
	语句1;
	语句2;
	if (条件表达式) {
		if (条件表达式) {
		
		} else {
		
		}
	} else {
	
	}
}

8 循环

8.1 三种循环结构

① while 循环
while (条件表达式) {
	语句1;
	语句2;
	......
}
② do while
do {
	语句1;
	语句2;
	......
} while (条件表达式);
③ for 循环
for (循环标记变量初始化; 条件表达式; 循环标记变量的变化) {
	语句1;
	语句2;
	......
}

每次循环,先执行大括号里的语句,再执行循环标记变量的变化;

9 跳转语句

continue 跳出本次循环,下一次循环继续。

break    跳出生个循环。

10 数组

2.1 数组的概念

  • 数组是值的有序集合。
  • 数组的每个成员称之为 元素; 数组由元素组成。
  • 每个元素都有一个索引
  • 数组元素的索引从 0 开始,索引必须是连续的。

2.2 定义数组(创建数组)

① 直接量方式
var nameList = [];
var nameList = [100,200,300,40];
var nameList = ['曹操', 100, true, null, undefined, [100, 200, 300]];
② 构造函数方式
var arr1 = new Array();   //创建了一个数组 空数组
var arr2 = new Array(100,200,'曹操',[1,2,3,4]);   // 创建数组,指定元素
var arr3 = new Array('hello'); // 创建一只有一个元素的数组,元素的值是 "hello"
var arr4 = new Array(20);   // 创建数组,指定数组元素的个数
var arr5 = [10];    // 创建一个只有一个元素的数组,元素的值是 10

如果 Array 只有一个参数,参数如果是字符串,就创建只有一个元素的数组,元素的值是字符串

参数如果是数字,数字会被认为是数组元素的个数(数组的长度)

2.3 读取数组的元素

数组[索引]  取值可以设置元素的值
数组有个 length 属性,通过该属性可以获取数组的长度(数组中元素的个数)

2.4 稀疏数组

如果数组中存在没有值的元素,该数组称之为稀疏数组。
JS 数组要求数组的索引必须是连续的,如果跳跃索引进行赋值,数组会补齐中间的元素(自动补齐的这些元素没有值)

尽量的避免稀疏数组

2.5 遍历数组(迭代数组)

① for 循环方式(推荐)
for (var i = 0; i < arr.length; i ++) {
	i; // 元素的索引
	arr[i];  // 元素的值
}
② for in 方式
for (var i in arr) {
	i; // 元素的索引
	arr[i]; // 元素的值
}

2.6 数组元素的添加和删除

① 添加
方式一:  [] 指定数组的下一个索引 (不推荐)  nameList[9] = value;

方式二: 利用数组长度作为下一个索引 nameList[nameList.length] = value;

方式三: push() 方法在数组的后面添加一个或多个元素   
		nameList.push(value);
		nameList.push(value,value, value ....)

方式四: unshift() 方法在数组的前面添加一个或多个元素   
		nameList.unshift(value);
		nameList.unshift(value1, value2, value3...)

方式五: splice() 方法在指定的位置插入一个或多个元素
		 nameList.splice(要插入的位置索引, 0, value)
		 nameList.splice(要插入的位置索引, 0, value1, value2, value3, value4 ....)

② 删除
方式一: 通过设置数组的length的属性实现删除数组元素的目的
		arr.length -= 1;  // 删除最后一个元素
		arr.length -= 3;  // 删除后三个元素
		arr.length = 0;   // 清空数组
		
方式二: 使用 pop() 方法,删除数组的最后一个元素
		arr.pop();   // 一次只能删除一个
		
方式三: 使用 shift() 方法,删除数组的第一个元素
		arr.shift();   // 一次只能删一个
		
方式四: splice() 方法 删除指定位置指定数量的元素
		arr.splice(要删除的索引, 要删除的数量)

2.7 字符串的数组特性

字符串也具有 length 属性,可以获取字符串中字符的个数
字符串中的每个字符也有索引,也是从0开始,可以通过 [索引] 获取到字符串中的某个字符
可以使用 for 循环遍历字符串中的每个字符
无法修改字符串中的某个字符
字符串的 length 也无法设置

把具有数组特性但又不是数组的一些对象称之为类数组对象伪数组对象

11 函数

1 函数的概念

什么是函数?
	函数是具有特定功能的代码块。
	只有调用函数代码块才执行,多次调用就多次执行
	
函数的作用?
	通过函数可以让代码在需要的时候再去执行
	提高代码的重用性
	

函数的组成:
	函数名,函数名的命名规则与变量名的命名规则相同。
	参数,分为形参和实参
	返回值
	函数体

2 定义函数的三种方式

① function 关键字方式 / 字面量方式 (常用)
function 函数名() {
    
}
function 函数名(参数1,参数2) {
    
}
② 表达式方式
var 函数名 = function(){

}
var 函数名 = function(参数1,参数2{

}
③ Function 构造函数方式(不推荐)
var 函数名 = Function('函数体');
var 函数名 = Function('参数1', '参数2', '参数3', '函数体');

3 函数的调用和函数的返回值

3.1 函数的调用
函数名的后面加() 才是调用,函数内的代码才会执行!
函数名后面没有(),不是函数的调用,函数内的代码不会执行!
函数名后面跟() 称之为函数调用表达式,值是函数的返回值
只有函数名 称之为函数名表达式,值是函数本身
3.2 函数的返回值
① return 表示函数的返回值,return 后面通常跟个表达式, 作为函数调用表达式的值;

② 一个函数如果没有return,或者 return 的右边是空的,函数的默认返回值是 undefined。

③ return 代码会终止函数的执行; return 下面的代码不会执行。

什么时候需要些 return ?

如果函数的功能是为了进行某种计算,计算结果通产需要以返回值的形式呈现

4 函数的参数

4.1 形参和实参
形参: 声明函数的时候,里面参数就是形参;相当于还没有给值的变量。
实参: 调用函数的时候,给的参数; 实参会按照顺序依次赋值给形参。
4.2 形参和实参的数量问题
实参数量>形参数量: 多出来的实参不会有任何功能;
实参属性<形参数量:实参按照顺序给形参赋值,后面的形参可以赋不上值,取 undefined
4.3 参数的默认值
写法一: 旧的写方法(兼容性好)
	function fn(a, b){
		if (b === undefined) {
			b = 默认值
		}
	}
	
	
写法二: ES6 支持
	function fn(a, b='默认值') {
	
	}

注意:

有默认值的参数一定放在后面。(如果一个参数有默认值,后面的其他参数也要有默认值)

如果参数有默认值,调用函数的时候可以不指定与之对应的实参

4.4 arguments
arguments 只能在函数内使用
arguments 是所有实参的集合,是一个类数组对象;可以像数组那样遍历,取其中的元素。
利用 arguments 可以实现参数数量不定的函数

5 变量的作用域

5.1 全局变量和局部变量
全局变量:
	在函数外边声明的变量就是全局变量
	作用域范围是全局
	
局部变量:
	在函数内定义的变量的就是局部变量
	作用域范围是本函数内(定义变量的函数内)

如果函数内定义的变量没有加 var,该变量是全局变量!!

作用域: 变量的可作用范围!

5.2 作用域链
作用域链产生的原因?
	函数里面可以嵌套函数,形成了作用域链
	
什么是作用域链?
	作用域链描述的是变量的查找过程
	先从本作用域中查找,如果找到就使用,如果找不到取上层作用域找,一直找到全局作用域,找到就停下来,如果到最后仍然找不到报错“not defined”

变量的作用域只于函数声明的位置有关系,与函数调用的位置没有关系!!

6 变量提升

6.1 变量提升
JS 在预解析的时候会把变量的声明提升到本作用域的最前面
只提升了变量的声明,变量的值没有提升,所以在变量声明语句之前使用变量会得到 undefined
正式解析的时候,执行到了变量声明语句,会给已经提升的变量赋值

注意: 不使用 var 声明的变量,不会提升

6.2 函数提升
JS 在预解析的时候会把函数提升到本作用域的最前面
函数的提升会把函数的声明和函数的值一起提升,所以函数可以在函数声明语句之前被调用!
如果函数和变量同名,函数的提升权重更高
正式解析的时候,执行到了函数声明语句会跳过

注意:

如果用表达式方式或者构造函数方式声明的函数,提升规则与变量一致; 只提升声明不提升值,正式解析的时候执行到声明语句再赋值。

7 自调用函数

7.1 匿名函数
没有名字的函数就是匿名函数
匿名函数其实是个函数直接量
// 一个匿名函数赋值给了变量 fn
var fn = function(){
    
}
7.2 自调用函数
函数声明完直接调用的函数就是自调用函数
自调用函数通常都是匿名函数
// 自调用函数
// 匿名函数
// 匿名自调用函数
(function(){
    console.log('啊,我是个匿名函数');
})();


// 声明有名字的函数
// 自调用函数
(function fn(){
    console.log('啊,我是函数我的名字是 fn');
})();
7.3 自调用函数的作用
1. 创建一个独立的作用域,避免变量互相混淆,减少全局变量的使用,避免全局变量污染
   实际开发中,把每个页面效果都写在一个自调用函数内
   
2. 实现JS的模块化,每个模块的代码都写在一个自调用函数中。   
7.4 自调用函数语法规则
1. 自调用函数也可以有参数和返回值(大部分自调用函数没有返回值)

2. 连续写两个自调用函数,中间没有分号,会报错(引起语法歧义)
   解决:
   	① 加分号
   	② 获取在自调用函数的前面加 !

8 回调函数

8.1 什么是回调函数

回调函数满足三个条件:

① 函数是我定义的。

② 我没有调用函数。

③ 函数最终却执行了。

匿名函数比较适合作为回调函数。

8.2 使用回调函数的场景
如果一个函数作为其他函数的参数,作为参数的那个函数通常是个回调函数
JS中使用回调函数的场景:
① 事件函数
② 定时器函数
③ ajax 回调函数
④ 框架中的声明周期钩子函数
8.4 函调函数的实现
/**
 * @param {Function} callback
 */
function func(callback) {
    // callback 是个函数,调用
    callback();
}

//func(100);
// 匿名函数作为回调函数
func(function(){
    console.log('hello,我是匿名函数');
});

// 有名字的函数作为回调函数
function fn(){
    console.log('hello,我是函数 fn');
}
func(fn);

9 递归函数

1. 函数内部再次调用自己,称之为函数的递归调用,这样的函数叫递归函数

2. 正常的递归函数,必须有个结束条件,而且随着递归调用次数的增加,应该越来越趋近于递归结束的条件

3. 递归运行效率较低,理解难度大,建议用循坏代替(如果可用用循环代替的话)

Object 对象

1 Object 对象的概念

1. 值的无序集合
2. object 对象由属性组成
3. 属性有属性名和属性值
4. 属性的值如果是 function 类型的数据,这种属性也称之为“方法”

2 创建一个 Object 对象

1. 直接量方式
   var 对象名 = {
       属性:,
       属性:};


2. Object 构造函数方式
	var 对象名 = new Object();

Object 构造函数方式只能先创建空对象,再添加属性;

直接量方式可以创建空对象,也可以在创建的同时添加属性。

3 读写对象的属性

1. 两种语法:
	可以使用 .语法   对象名.属性名
	可以使用 []语法  对象名['属性名']
	
2. 读写规则
	读: 如果读取的属性不存在,返回 undefined
	设置(写): 如果设置的属性是对象原本就有的,会对属性值就行修改;
	           如果是对象中不存在的属性,会添加该属性。
	           
3. 一下两种情况必须使用 [] 语法读写属性
	① 属性名的命名规范不符合标识的命名规范(变量名的命名规范)
	② 变量的值作为属性的名字

4 遍历对象中每一个属性

for (var i in person) {
    console.log(i, person[i]);
}

i 是变量,值是每次遍历出来的属性名,通过 i 取到属性的值,必须使用 [] 语法。

对象默认没有 length 属性

5 删除属性

delete person.name;
delete person['a#b-c'];

6 判断对象中是否包含某个属性

'name' in person

in 运算符是二元运算符,运算符的左边写属性名,右边写对象

in 运算符组成的表达式的值是一个布尔值, true 表示对象中包含该属性,false 表示对象中没有该属性。

属性名必须以字符串的形式给出,写在引号里; 没有引号会被当做变量,就会把变量的值作为属性名。

构造函数

1. 构造函数的概念

1. 构造函数是对对象的描述;规定了对象的各项特性(属性、方法以及其他特性)
2. 对象是根据构造函数产生的, 产生于相同构造函数的对象具有相同的特性。
3. 构造函数相当于其他编程语言中的 类
4. JS 中,所有的数组来自于同一个构造函数,所有的Object来自于同一个构造函数,所有的Function 也来自于同一个构造函数,所有的字符串也来自于同一个构造函数.....
   构造函数决定了数据类型
对象和构造函数的关系:
① 对象是构造函数的实现(实例),构造函数是对象的抽象(描述)
② 一个对象只能有一个构造函数,一个构造函数可以产生多个对象。

2 判断一个对象是否是构造函数的实例

① instanceof 运算符 
  用法:  对象 instanceof 构造函数;   表达式的值如果是 true,说明对象是该构造函数的实例;
  
② constructor 属性
  所有的对象都有 constructor 这个属性,该属性返回这个对象的构造函数
 

原始类型中的 Number、String、Boolean 具有两种状态,一种是原始值的状态,一种是对象的状态;会根据运行环境自动切换两种状态。

所有数字的构造函数是 Number

所有字符串的构造函数是 String

所有布尔值的构造函数是 Boolean

所有数组的构造函数是 Array

所有对象(Object对象)的构造函数都是 Object

所有函数的构造函数都是 Function

3 自定义构造函数

// 定义构造函数
// 通过构造函数规定对象的属性和方法
function Person(name, age, weight){
    // 给对象设置属性
    this.name = name;
    this.age = age;
    this.weight = weight;
    // 给对象设置方法
    this.say = function(){
        // 在方法中可以使用其他属性
        console.log('我叫'+this.name+',我'+this.age+'岁了,我体重'+this.weight+'斤');
    }
}

定义构造函数,与定义普通函数一样; 为了以示区别,通常构造函数名字的首字母大写。

在构造函数中使用 this, this 表示构造函数要创造成的对象。给 this 添加属性就是给构造函数创造出来的对象添加属性

4 对象的实例化

对象的实例化是根据构造函数创造对象的过程!

new Person();
new Person('安妮', 19, 120);
new Person;  

如果构造函数没有要求参数,实例化的时候可以省略括号!

5 构造函数和函数

1. 定义构造函数和定义函数是一样的代码,是一个函数还是一个构造函数取决于我们怎么去用
2. 实例化构造函数,构造函数内部的代码也会执行;调用函数,函数内部代码会执行(相似的地方)
3. 实例化构造函数,在执行里面代码的同时还会创造一个对象;调用函数就是单纯的执行里面的代码。
4. 实例化构造函数表达式的值是一个对象,函数调用表达式的值是函数的返回值。

this

1 this 的概念

1. this 通常在函数或方法中使用
2. this 是个内置的变量,指向一对象

2 this 的指向

第一种情况: this 在构造函数中使用
	this 指向构造函数实例化成的对象
	
第二种情况: this 在方法或函数中使用
	this 指向调用该方法的对象
	
特殊情况(非严格模式下)
	函数外面知己使用 this,指向 window

全局变量本质上是window的属性,函数本质上是window的方法。

使用 window 的属性和方法的时候,可以省略 window。

一个函数如果前面没有 对象.,那么是window在调用这个函数。

3 window

JS 有一个全局对象,在浏览器上运行的js 全局对象就是 window
全局变量本质上是window的属性,函数本质上是window的方法。
使用 window 的属性和方法的时候,可以省略 window。
一个函数如果前面没有 `对象.`,那么是window在调用这个函数。

原型

4.1 原型的概念

1. 原型是个对象。
2. 所有的对象都有原型。
3. 对象可以继承(使用)原型上的方法和属性。

4.2 获取原型

// 第一种方式 对象本身获取 隐式原型
对象.__proto__;   // 非标准属性(大部分浏览器支持)


// 第二种方式 对象的构造函数获取  显示原型
构造函数.prototype;  // 标准属性

构造函数相同的对象,原型也是一样的!

相同数据类型的对象,原型一致;比如所有数组的原型都是一样的,所以字符串对象的原型都是一样的…

4.3 原型的应用

// 定义构造函数
function Person(name, age) {
    // 给对象添加属性
    this.name = name;
    this.age = age;

}

// 把方法添加到对象的原型上
Person.prototype.say =  function(){
    console.log('我叫'+this.name+',我今年'+this.age+'岁了');
};
属性添加到对象本身上,方法(值相同的属性)一般添加到对象的原型上。

好处:
    每实例化一个对象,内存就会开辟一块新的空间,存储对象的属性。
    如果对象的方法都设置在原型上,只有存在原型对象上就可以了;不需要每个对象都存储一遍。(达到节省内存的目的)

4.4 对象、构造函数、原型之间的关系

对象和构造函数:
	对象是构造函数的实例,构造函数是对象的抽象
	通过 对象.constructor 可以获取到该对象的构造函数
	
对象和原型:
	对象可以使用(继承)定义在原型上的属性和方法
	通过 对象.__proto__ 可以获取该对象的原型
	
构造函数和原型:
	相同构造函数的实例(对象),原型也是相同的
	通过 构造函数.prototype 可以获取该构造函数实例(对象)的原型

4.5 判断一个属性是否是对象本身的属性

对象.hasOwnProperty('属性名')
// 返回 true, 说明该属性是对象本身的属性
// 返回 false,说明该属性不是对象本身的属性

与 in 运算符的区别:

hasOwnProperty() 方法只有对象本身的属性才返回 true

in 运算符组成的表示,本身的属性以及原型上的属性都是 true

原型链

5.1 原型链的概念

所有的对象都有原型
原型也是个对象
原型也有原型
对象由原型,原型还有原型,一直到一个没有原型的对象(Object.prototype),构成原型链

5.2 原型链的作用

原型链描述的就是属性的查找过程:

当使用对象的某个属性时,先从对象本身上查找,如果找不到从对象的原型上查找,如果还找不到继续从原型的原型山查找,直到顶层的原型对象(Object.protype); 从哪里找到就从哪里停止,一直找不到,返回 undefined

5.3 关于 .constructorinstanceof

.constructor
	本意是获取该对象的构造函数
    有些情况下,constructor并非获取本对象的构造函数;如数组的原型,  Array.prototype.constructor 返回的是 Array, 但是 Array.prototype 的构造函数是 Object; Array.prototype 的 constructor 属性不是给自己用的,是给数组实例是的。
    
    
instanceof of
	使用 instanceof 判断一个对象是否是构造函数的实例, 判断对象自己的构造函数成立,判断对象与对象原型的构造函数也成立
    如:
    数组 instanceof Array;  // true
	数组 instanceof Object;  // true  因为数组的原型的构造函数是 Object


原型链顶层的对象,Object.prototype 也是Object 的实例!

值类型和引用类型

值类型: 所有的原始类型都是值类型。 也叫不可变类型。
引用类型: 所有的对象类型都是引用类型。 也叫可变类型。

值类型和引用类型的区别
	内存存储形式不同; 值类型存储在栈结构中; 引用类型栈结构中存的是地址,对象存在堆结构中。
	如果一个变量的值是引用类型,变量1赋值给变量2,那么变量1和变量2会指向相同的一个对象


可变类型和不可变类型:
	可变类型: 我们可以修改数组的元素,可以修改对象的属性
	不可变类型: 我们不能修改字符串或数字中一部分。

js内置对象

1. Number

属性:
	Number.MAX_VALUE
	Number.MIN_VALUE

方法:
	toFixed()
	toString()

2. String

属性:
	length
	
方法:
	slice()
	substring()
	substr()
	indexOf()
	lastIndexOf()
	sqlit()
	toUpperCase()
	toLowerCase()
	replace()
	charCodeAt()
	String.fromCharCode()

3 Math

属性:
	Math.PI
	
方法:
	Math.abs()
	Math.sqrt()
	Math.pow()
	Math.max()
	Math.min()
	Math.round()
	Math.floor()
	Math.ceil()
	Math.random()

4 Date

实例化:
	new Date()
	
方法:
	getFullYear()
	getMonth()  
	getDate()
	getDay()
	getHours()
	getMinutes()
	getSeconds()
	getMilliseconds()
	
	getUTC...
	
	set...
	setUTC..
	
	getTime()   
	Date.now()
	setTime()

5 Array

属性
	length
	
方法:
	访问方法(不会修改调用方法的对象)
	concat()
	join()
	slice()
	修改器方法:
	push()
	pop()
	unshift()
	shift()
	splice()
	sort()
	reverse()
	
ES5 方法:(访问方法)
	indexOf()  返回某个元素在数组中第一次出现的位置 元素不存在返回 -1
	lastIndexOf()
	forEach()  数组遍历
	filter()   数组过滤,返回过滤好的数组
	map()      返回新数组,新数组的元素是回调函数的返回值
	some()     返回布尔值,回调函数有一个返回true,some()返回值就是true
	every()    返回布尔值,回调函数必须都返回true,every() 返回才是true
	reduce()        返回最后一次回调的返回值
	reduceRight()   返回最后一次回调的返回值

6 Function

方法:
	call()     调用函数的同时设置this的指向;  fn.call(obj, fn的参数1, fn的参数2....)
	apply()    调用函数的同时设置this的指向;  fn.apply(obj, [fn的参数1, fn的参数2....])
	bind()     返回设置了this指向的函数,其他规则同 call 相同

7 JSON

方法:
JSON.stringify()    把js的对象或数组转为 json 格式的字符串
JSON.parse()        把 json 格式的字符串转为 js 的对象或数组

json 是一种数据交换格式;参考了 js 的数组和对象的语法;

8 全局对象

eval()   把字符串当做代码执行
encodeURI()  对URL进行编码
decodeURI()  对编过码的url进行解码

Number()、String()、Array()、Object()、isNaN、isFinite、NaN 等本质上都是全局对象的属性(方法)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值