javascript ---- 超哥

javascript ---- 超哥,第1张

文章目录 🍀基本语法入门helloworldjs编写位置 基本语法注释字面量 & 变量 (概念)标识符🍃数据类型StringNumberBooleanNullUndefined 🟥强制类型转换xxx-->String方式一: 调用被转换数据类型的`toString()方法`方式二:调用String()函数,并将被转换的数据作为参数传递给函数方式三:运用 + 运算符 xxx-->Number转换方式一:使用Number()函数转换方式二:「这种方式专门用来对付字符串」方式三: 通过 - * / 转换方式四: 一元运算符 + xxx-->Boolean: 使用Boolean()函数方法一:使用Boolean()函数方法二:逻辑!运算符 🍃运算符算数运算符一元运算符自增 & 自减逻辑运算符赋值运算符关系运算符相等运算符条件运算符 代码块流程控制 面向对象🍃对象`对象的分类:``创建对象`方式一:`new Object()`方式二:`字面量形式 函数(function)作用域`全局作用域``变量的声明提前``函数的声明提前` `函数作用域` this工厂方法创建对象构造函数原型 prototypetoString垃圾回收 内建对象数组(Array)Date对象Math包装类字符串相关方法正则表达式 宿主对象DOM

视频
资料

🍀基本语法 入门
helloworld
<!--JS代码需要编写到script标签中-->
<script type="text/javascript">
	
	/*
	 * 控制浏览器d出一个警告框
	 * alert("哥,你真帅啊!!");
	 */
	
	/*
	 * 让计算机在页面中输出一个内容
	 * document.write()可以向body中输出一个内容
	 * document.write("看我出不出来~~~");
	 */
	
	/*
	 * 向控制台输出一个内容
	 * console.log()的作用是向控制台输出一个内容
	 * console.log("你猜我在哪出来呢?");
	 */
	
	alert("哥,你真帅啊!!");
	document.write("看我出不出来~~~");
	
	console.log("你猜我在哪出来呢?");
</script>

js代码是从上到下依次执行的
严格区分大小写


js编写位置
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		
		<!--
			可以将js代码编写到外部js文件中,然后通过script标签引入
			写到外部文件中可以在不同的页面中同时引用,也可以利用到浏览器的缓存机制
			推荐使用的方式
		-->
		<!--
			script标签一旦用于引入外部文件了,就不能在编写代码了,即使编写了浏览器也会忽略
			如果需要则可以在创建一个新的script标签用于编写内部代码
		-->
		<script type="text/javascript" src="js/script.js"></script>
		<script type="text/javascript">
			alert("我是内部的JS代码");
		</script>
		
		<!--
			可以将js代码编写到script标签	
		<script type="text/javascript">
			
			alert("我是script标签中的代码!!");
			
		</script>
		-->
	</head>
	<body>
		
		<!--
			可以将js代码编写到标签的onclick属性中
			当我们点击按钮时,js代码才会执行
			
			虽然可以写在标签的属性中,但是他们属于结构与行为耦合,不方便维护,不推荐使用
		-->
		<button onclick="alert('讨厌,你点我干嘛~~');">点我一下</button>
		
		<!--
			可以将js代码写在超链接的href属性中,这样当点击超链接时,会执行js代码
		-->
		<a href="javascript:alert('让你点你就点!!');">你也点我一下</a>
		<a href="javascript:;">你也点我一下</a>
		
	</body>
</html>

基本语法
注释

– 单行注释://注释内容
– 多行注释:/注释内容/

JS中严格区分大小写JS中每一条语句以分号(;)结尾
如果不写分号,浏览器会自动添加,但是会消耗一些系统资源
而且有些时候,浏览器会加错分号,所以在开发中分号必须写JS中会忽略多个空格和换行,所以我们可以利用空格和换行对代码进行格式化
字面量 & 变量 (概念)

字面量
比如 :1 2 3 4 5
字面量都是可以直接使用,但是我们一般都不会直接使用字面量

变量 : 变量可以用来保存字面量,而且变量的值是可以任意改变的
开发中都是通过变量去保存一个字面量,而很少直接使用字面量
可以通过变量对字面量进行描述

变量的声明:
– 使用var关键字声明一个变量。
var a;

变量的赋值:
– 使用=为变量赋值。
a=123;

声明和赋值同时进行:
– var a = 123;

//使用,运算符同时声明多个变量
//var a , b , c;

//可以同时声明多个变量并赋值
//var a=1 , b=2 , c=3;
//alert(b);		

标识符

指变量、函数、属性的名字,或函数的参数

命名一个标识符时需要遵守如下的规则:
1.标识符中可以含有字母、数字、_、$
2.标识符不能以数字开头
3.标识符不能是ES中的关键字或保留字
4.标识符一般都采用驼峰命名法


🍃数据类型

数据类型指的就是字面量的类型
在JS中一共有六种数据类型

String 字符串Number 数值Boolean 布尔值Null 空值Undefined 未定义Object 对象

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


String 在JS中字符串需要使用引号引起来使用双引号或单引号都可以,但是不要混着用引号不能嵌套,双引号不能放双引号,单引号不能放单引号在字符串中我们可以使用\作为转义字符,当表示一些特殊符号时可以使用\进行转义
\" 表示 "
\' 表示 '
\n 表示换行
\t 制表符
\ 表示\
var str = 'hello';
str = '我说:"今天天气真不错!"';

str = "我说:\"今天\t天气真不错!\"";

Number

① 在JS中所有的数值都是Number类型,包括整数和浮点数(小数)

//数字123
var a = 123;
//字符串123
var b = "123";

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

语法:typeof 变量检查字符串时,会返回string检查数值时,会返回numbe
console.log(typeof b); //string

③JS中可以表示的数字的最大值
Number.MAX_VALUE : 1.7976931348623157e+308
Number.MIN_VALUE: 5e-324 大于0的最小值

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

Infinity 表示正无穷-Infinity 表示负无穷使用typeof检查Infinity也会返回number
a = -Number.MAX_VALUE * Number.MAX_VALUE;
console.log(typeof a); //number

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

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

var c = 1865789 + 7654321;

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

var c = 0.1 + 0.2;
console.log(c);

Boolean

布尔值只有两个,主要用来做逻辑判断
true:表示真
false:表示假

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

var bool = false;
console.log(typeof bool); //boolean

Null

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

var a = null;
Undefined

Undefined(未定义)类型的值只有一个,就undefind
声明了未定义

var b
console.log(typeof b);//undefind

🟥强制类型转换

指将一个数据类型强制转换为其他的数据类型
类型转换主要指,将其他的数据类型,转换为
String Number Boolean


xxx–>String 方式一: 调用被转换数据类型的toString()方法 该方法不会影响到原变量,它会将转换的结果返回但是注意:null和undefined这两个值没有toString()方法,如果调用他们的方法,会报错
var a = 123;

//调用a的toString()方法
//调用xxx的yyy()方法,就是xxx.yyy()
a = a.toString(); //"123"

a = true;
a = a.toString(); //"true"

a = null;
//a = a.toString(); //报错

a = undefined;
//a = a.toString(); //报错
方式二:调用String()函数,并将被转换的数据作为参数传递给函数 使用String()函数做强制类型转换时,对于Number和Boolean实际上就是调用的toString()方法但是对于null和undefined,就不会调用toString()方法它会
将 null 直接转换为 “null”
将 undefined 直接转换为 “undefined”
//Number和Boolean实际上就是调用的toString()方法
a = 123;
//调用String()函数,来将a转换为字符串
a = String(a);

a = null;
a = String(a); // "null"

a = undefined;
a = String(a); // "undefined"
方式三:运用 + 运算符

传送
任何的值和字符串做加法运算***,都会先转换为字符串,然后再和字符串做拼串的 *** 作

var c = 123;
c = c + ""; // number --> string

xxx–>Number 转换方式一:使用Number()函数

字符串 --> 数字

如果是纯数字的字符串,则直接将其转换为数字如果字符串中有非数字的内容,则转换为NaN如果字符串是一个空串或者是一个全是空格的字符串,则转换为0

- 布尔 --> 数字

true 转成 1false 转成 0

null --> 数字 0

undefined --> 数字 NaN

var a = "123";
a = Number(a); //123

a = false;
a = Number(a); //0

a = null;
a = Number(a); //0

a = undefined;
a = Number(a);//NaN
转换方式二:「这种方式专门用来对付字符串」 parseInt() 把一个字符串转换为一个整数
parseInt()可以将一个字符串中的有效的整数内容去出来,然后转换为NumberparseFloat() 把一个字符串转换为一个浮点数如果对非String使用parseInt()或parseFloat()
它会先将其转换为String然后在 *** 作
a = "123567a567px";
a = parseInt(a); //123567

a = "123.456.789px";
a = parseFloat(a); //123.456


//非String使用parseInt()
a = true;
a = parseInt(a);// NaN

a = 198.23;
a = parseInt(a);// 198

其他进制数字
可以在parseInt()中传递一个第二个参数,来指定数字的进制
a = parseInt(a,10);

			
//十六进制
a = 0x10;
a = 0xff;
a = 0xCafe;

//八进制数字
a = 070;

//二进制数字
//a = 0b10;

//向"070"这种字符串,有些浏览器会当成8进制解析,有些会当成10进制解析
a = "070";

//可以在parseInt()中传递一个第二个参数,来指定数字的进制
a = parseInt(a,10);

方式三: 通过 - * / 转换

传送到知识点
可以通过为一个值 -0 *1 /1来将其转换为Number
原理和Number()函数一样,使用起来更加简单

a = "12" - 0; 
a = "12" * 1;
a = "12" / 1;

方式四: 一元运算符 +

传送到知识点
可以对一个其他的数据类型使用+,来将其转换为number
它的原理和Number()函数一样

+ 1 // 1

+ "1" // 1
+ "false" //NaN
+ "null" //NaN
 
+ null // 0

+ undefined // NaN

+ false // 0

xxx–>Boolean: 使用Boolean()函数 方法一:使用Boolean()函数

数字 ---> 布尔

除了0和NaN,其余的都是true
字符串 ---> 布尔除了空串,其余的都是true

null和undefined都会转换为false

对象也会转换为true

var a = 123; //true
a = -123; //true
a = 0; //false
a = Infinity; //true
a = NaN; //false

//调用Boolean()函数来将a转换为布尔值
a = Boolean(a);

//除了`空串`,其余的都是true
a = "hello" //true
a = " ";    //true
a = "false" //true
a = ""		//false
a = Boolean(a);


a = null; //false
a = Boolean(a);

a = undefined; //false
a = Boolean(a);

方法二:逻辑!运算符

知识电梯

如果对一个值进行两次取反,它不会变化如果对非布尔值进行元素,则会将其转换为布尔值,然后再取反
所以我们可以利用该特点,来将一个其他的数据类型转换为布尔值
可以为一个任意数据类型取两次反,来将其转换为布尔值,
原理和Boolean()函数一样
var b = 10;
b = !!b; //

!!0 //false
!!12 //true
!!-12 //true
!!NaN //false
!!Infinity

!!"0" //true
!!"false" //true
!!"" //false
!!"   "//true

!!null //false

!!undefined //false

🍃运算符

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

比如:typeof就是运算符,可以来获得一个值的类型
它会将该值的类型以字符串的形式返回
number string boolean undefined object
算数运算符 当对非Number类型的值进行运算时,会将这些值转换为Number然后再运算(除 + 对字符串外)任何值做- * /运算时都会自动转换为Number,
可以通过为一个值 -0 *1 /1来将其转换为Number
原理和Number()函数一样,使用起来更加简单

+

+对值进行加法运算,并将结果返回对两字符串进行加法运算,则会做拼串,会将两个字符串拼接为一个字符串,并返回
任何的值和字符串做加法运算,都会先转换为字符串,然后再和字符串做拼串的 *** 作
//number
var a = 123;
result = a + 1; //result = 124, a = 123
result = 456 + 789;//1245

//boolean、null、NaN
result = true + 1;//1 + 1 = 2
result = true + false;//1 + 0 = 1
result = 2 + null; // 2 + 0 = 2
result = 2 + NaN; //2 + 0 =2

//string
result = "你好" + "大帅哥";//你好大帅哥
result = 123 + "1"; //
result = true + "hello";

var c = 123;
c = c + ""; // number --> string
result = 1 + 2 + "3"; //33
result = "1" + 2 + 3; //123

-

可以对两个值进行减法运算,并将结果返回
result = 100 - 5; //95

result = 100 - true;//100 - 1 =99

result = 100 - "1";//100 - 1 = 99
result = 100 - "1a";//100 - NaN = NaN

result = 100 - null;//100 - 0 = 100

result = 100 - undefined;//100 - NaN = NaN

*

result = 2 * 2; //4

result = 2 * "8"; // 2 * 8 = 16

result = 2 * undefined; // 2 * NaN = NaN

result = 2 * null; // 2 * 0 = 0

result = 2 * true; // 2 * 1 = 2

/

result = 4 / 2; //2
result = 3 / 2; //1.5

result = 3 / "1"; //3 / 1 = 3
result = 3 / "1a"; // 3 / NaN = NaN 

result = 3 / true; //3 / 1 = 3
result = 3 / false //3 / 0 = Infinity

result = 3 / null; //3 / 0 = Infinity

result = 3 / undefined; //3 / NaN = NaN 

%
% 取模运算(取余数)

result = 9 % 3; //0
result = 9 % 4; //1
result = 9 % 5; //4

一元运算符

一元运算符,只需要一个 *** 作数
+ 正号
正号不会对数字产生任何影响

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

对于非Number类型的值,它会将先转换为Number,然后在运算可以对一个其他的数据类型使用+,来将其转换为number,它的原理和Number()函数一样
自增 & 自减

自增 ++

对于一个变量自增以后,原变量的值会立即自增1后++(a++) 和 前++(++a)
无论是a++ 还是 ++a,都会立即使原变量的值自增1
a++的值等于原变量的值(自增前的值)
++a的值等于新值 (自增后的值)

自减 --: 同自增

var num = 10;
num = ++num;//11
num = num++;//11

分析num =  ++ num
① num自增运算
局部变量:11		 *** 作数栈:
② 压入 *** 作数栈
局部变量:11		 *** 作数栈:11
③ 赋值 *** 作(将 *** 作数栈的值赋值给局部变量num)
局部变量:11		 *** 作数栈:
num = 11


分析num = num ++ 
num = 11 局部变量
① 将局部变量压入 *** 作数栈
局部变量:11		 *** 作数栈:11
② 局部变量自增
局部变量:12		 *** 作数栈:11
③ 赋值 *** 作(将 *** 作数栈的值赋值给局部变量num)
局部变量:11		 *** 作数栈:
num = 11


var i = 1;
i = i++;
var j = i++;
var k = i + ++i*i++;

分析:
var i = 1;
i = i++;//通过上面知识易得 i = 1

var j = i++;//通过上面知识易得 j = 1,i=2

var k = i + ++i*i++;
1.压栈 *** 作时从左向右,i 的值入栈
i = 22

2. ++i 先自增,后入栈
i = 32 3

3. i++ 先入栈,后自增
i = 32 3 3
  ↓
i = 42 3 3	

4.做运算 先乘
3*3 = 9 
i = 42 9

5.做运算 加 *** 作
2 + 9
i = 411

6. 赋值 *** 作
将 *** 作数栈的值赋给 k 变量
i = 4		栈 
k = 11
j = 1

逻辑运算符

JS中为我们提供了三种逻辑运算符
! 非

所谓非运算就是值对一个布尔值进行取反 *** 作,true变false,false变true如果对一个值进行两次取反,它不会变化如果对非布尔值进行元素,则会将其转换为布尔值,然后再取反
所以我们可以利用该特点,来将一个其他的数据类型转换为布尔值
可以为一个任意数据类型取两次反,来将其转换为布尔值,
原理和Boolean()函数一样
var a = false;
a = !a; // true

var b = 10;
b = !!b; //

!!0 //false
!!12 //true
!!-12 //true
!!NaN //false
!!Infinity

!!"0" //true
!!"false" //true
!!"" //false
!!"   "//true

!!null //false

!!undefined //false

&& 与

两个值中有false就false,只有两个值都为true,才trueJS中的“与”属于短路与,如果第一个false,则不会看第二个值

|| 或

两个值中只要有true,就true如果两个值都为false,才falseJS中的“或”属于短路或,如果第一个true,则不会检查第二个值

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

与运算

第一个值为true,则必然返回第二个值第一个值为false,则直接返回第一个值

或运算

第一个值为true,则直接返回第一个值第一个值为false,则返回第二个值
1 && 2; //2
0 && 1; //0
//同理
NaN && 0; //NaN
0 && NaN; //0
//同理
"aaa" && 666 //666
"aaa" && "bbb" //"bbb"
"" && 666 //""

2 || 1 //2
2 || NaN; //2
2 || 0; //2
NaN || 1; //1
NaN || 0; //0

-1 || "你好";  // -1
"" || "hello"; //"hello"

赋值运算符
  =
  	可以将符号右侧的值赋值给符号左侧的变量
  += 
  	a += 5 等价于 a = a + 5
  -=
  	a -= 5 等价于 a = a - 5
  *=
  	a *= 5 等价于 a = a * 5
  /=
  	a /= 5 等价于 a = a / 5
  %=
  	a %= 5 等价于 a = a % 5

关系运算符

比较两个值之间的大小关系,关系成立返回true,不成立返回false
> 大于号
>= 大于等于
< 小于号
<= 小于等于

非数值的情况

非数值比较时,会将其转换为数字再比较符号两侧的值都是字符串时,不会将其转换为数字进行比较
而会分别比较字符串中字符的Unicode编码
相等运算符

==

当使用==来比较两个值时,类型不同,则会自动进行类型转换,将其转换为相同的类型,然后在比较转换的类型不一定,大部分情况转员numberundefined 衍生自 null,所以这两个值做相等判断时,会返回trueNaN不和任何值相等,包括他本身通过isNaN()函数来判断一个值是否是NaN
1 == 1; //true
1 == "1"; //true (string --> number)

true == "1" //true (string --> number ,boolean --> number)
true == "hello" //false (string --> number ,boolean --> number)

null == 0 //false

undefined == null //true

NaN == NaN //false

//判断b的值是否是NaN
var b = NaN;
isNaN(b)

!=
同上

===
判断两个值是否全等,它和相等类似,不同的是它不会做自动的类型转换
!==


条件运算符

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

a > b ? alert("a大"):alert("b大");

代码块

JS中{} 只有分组作用没有作用域作用


流程控制

1.条件判断语句
2.条件分支语句
3.循环语句

if语句

if(a > 10 && a <= 20){
	alert("a大于10,并且 a小于等于20");
}	
if(age > 17 && age <= 30){
	alert("你已经成年了");
}else if(age > 30 && age <= 60){
	alert("你已经中年了");
}else if(age > 60 && age <= 80){
	alert("你已经退休了");
}else{
	alert("你岁数挺大的了~~");
}

switch语句

switch(num){
	case 1:
		console.log("壹");
		//使用break可以来退出switch语句
		break;
	case 2:
		console.log("贰");
		break;
	case 3:
		console.log("叁");
		break;
	default:
		console.log("非法数字~~");
		break;
}

while循环

while(true){
	alert(n++);
	
	//判断n是否是10
	if(n == 10){
		//退出循环
		break;
	}
}

do while

do{
	document.write(i++ +"
"
); }while(i <= 10);

for

for(var i = 0 ; i < 10 ; i++ ){
	alert(i);
}

break

outer:
for(var i=0 ; i<5 ; i++){
	console.log("@外层循环"+i)
	for(var j=0 ; j<5; j++){
		break outer;
		console.log("内层循环:"+j);
	}
}

continue

outer:
for(var i=0 ; i<5 ; i++){
	for(var j=0 ; j<5 ; j++){
		continue;
		console.log("-->"+j);	
	}
	console.log("@--->"+i);
}

常用方法

console.time("test");
console.timeEnd("test");
Math.sqrt(i)

面向对象 🍃对象 对象的分类:

内建对象 (类似jdk中的类)
由ES标准中定义的对象,在任何的ES的实现中都可以使用
比如:Math String Number Boolean Function Object…

宿主对象(浏览器对象)
由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象
比如 BOM DOM

自定义对象
由开发人员自己创建的对象


创建对象 对象的属性可以是任何数据类型,也可以是一个函数当函数是一个对象的属性:称该函数时该对象的方法 方式一:new Object()

使用new关键字调用的函数,是构造函数constructor
构造函数是专门用来创建对象的函数
使用typeof检查一个对象时,会返回object

var obj = new Object();
//向obj中添加一个name属性
obj.name = "孙悟空";
//向obj中添加一个gender属性
obj.gender = "男";
//向obj中添加一个age属性
obj.age = 18;
//读取对象中的属性
obj.name = "tom";
//修改对象的属性值
obj.name = "tom";
//删除对象的属性
delete obj.name;
方式二:`字面量形式

对象字面量的属性名可以加引号也可以不加,建议不加,
如果要使用一些特殊的名字,则必须加引号

var obj = {};
obj.name = "孙悟空";


var obj2 = {			
	name:"猪八戒",
	age:13,
	gender:"男",
	test:{name:"沙僧"}
};

函数(function) 函数也是一个对象函数中可以封装一些功能(代码),在需要时可以执行这些功能(代码)函数中可以保存一些代码在需要的时候调用使用typeof检查一个函数对象时,会返回function
var fun = new Function("console.log('Hello 这是我的第一个函数');");

我们在实际开发中很少使用构造函数来创建一个函数对象

使用函数声明创建对象

function fun2(){
	console.log("这是我的第二个函数~~~");
	alert("哈哈哈哈哈");
	document.write("~~~~(>_<)~~~~");
}

函数表达式声明

var fun3 = function(){
	console.log("我是匿名函数中封装的代码");
};

形参声明,调用

调用函数时解析器不会检查实参的类型多余实参不会被赋值,如果实参的数量少于形参的数量,则没有对应实参的形参将是undefined
function sum(a,b){
	console.log("a = "+a);
	console.log("b = "+b);
	console.log(a+b);
}

sum(1,2);

实参可以是一个对象,也可以是一个函数

function fun(a){
	console.log("a = "+a);
	//a(obj);
}
fun(function(){alert("hello")});

返回值

return后的值将会会作为函数的执行结果返回,可以定义一个变量,来接收该结果如果return语句后不跟任何值就相当于返回一个undefined如果函数中不写return,则也会返回undefinedreturn后可以跟任意类型的值,也可以是一个对象,也可以是一个函数变量result的值就是函数的执行结果
function sum(a , b , c){
	//alert(a + b +c);
	var d = a + b + c;
	return d;				
}

var result = sum(4,7,8);
function fun2(){
	//返回一个对象
	return {name:"沙和尚"};
}

function fun3(){
	//在函数内部再声明一个函数
	function fun4(){
		alert("我是fun4");
	}
	//将fun4函数对象作为返回值返回
	return fun4;
}

fun3()();

立即执行函数

函数定义完,立即被调用,这种函数叫做立即执行函数立即执行函数往往只会执行一次
(function(){
	alert("我是一个匿名函数~~~");
})();

对象属性

可以是任何数据类型,也可以是函数当函数时对象属性,称该函数时对象的方法
var obj2 = {
	
	name:"猪八戒",
	age:18,
	sayName:function(){
		console.log(obj2.name);
	}
};

obj2.sayName();

枚举对象中的属性
for…in语句 对象中有几个属性,循环体就会执行几次
每次执行时,会将对象中的一个属性的名字赋值给变量

var obj = {
	name:"孙悟空",
	age:18,
	gender:"男",
	address:"花果山"
};

for(var n in obj){
	console.log("属性名:"+n);
	//当对象的属性是变量时,使用[]调用
	console.log("属性值:"+obj[n]);
}

作用域 全局作用域

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

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

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

在全局作用域中:
创建的变量都会作为window对象的属性保存
创建的函数都会作为window对象的方法保存

var a = 10;
var b = 20;
var c = "hello";
console.log(window.c);


function fun(){
	console.log("我是fun函数");
}
window.fun();

变量的声明提前

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

console.log("a = "+a);//undefined
var a = 123;

console.log("a = "+a);//报错
a = 123;

函数的声明提前

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

fun();
//函数声明,会被提前创建
function fun(){
	console.log("我是一个fun函数");
}
//函数表达式,不会被提前创建
var fun2 = function(){
	console.log("我是fun2函数");
};

fun2();

函数作用域 调用函数时 创建函数作用域,函数执行完毕以后,函数作用域销毁每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的在函数作用域中可以访问全局作用域的变量,在全局作用域中无法访问到函数作用域的变量先找自身作用域,有就用,没有则向上找,直到找到全局作用域,全局中依然没有,则报错ReferenceError在函数中要访问全局变量可以使用window对象
//创建一个变量
var a = 10;

function fun(){
	
	var a = "我是fun函数中的变量a";
	var b = 20;
	
	//console.log("a = "+a);
	
	function fun2(){
		//使用window对象
		console.log("a = "+window.a);
	}
	
	fun2();
	
}
函数作用域也有声明提前的特性,使用var关键字声明的变量,会在函数中所有的代码执行之前被声明,函数声明也会在函数中所有的代码执行之前执行使用var关键字声明的变量,会在函数中所有的代码执行之前被声明
function fun3(){
	
	fun4();
	
	//console.log(a);
	
	var a = 35;
	
	function fun4(){
		alert("I'm fun4");
	}
}
在函数中,不使用var声明的变量都会成为全局变量定义形参就相当于在函数作用域中声明了变量
this 解析器在调用函数每次都会向函数内部传递进一个隐含的参数,
这个隐含的参数就是this,this指向的是一个对象,
这个对象我们称为函数执行的 上下文对象,
根据函数的调用方式的不同,this会指向不同的对象
1、以函数的形式调用时,this永远都是window
2、以方法的形式调用时,this就是调用方法的那个对象
3、当以构造函数的形式调用时,this就是新创建的那个对象
function fun(){
	//console.log("a = "+a+", b = "+b);
	console.log(this.name);
}
//创建一个name变量
var name = "全局";

//创建一个fun()函数
function fun(){
	console.log(this.name);
}

//创建两个对象
var obj = {
		name:"孙悟空",
		sayName:fun
};

var obj2 = {
		name:"沙和尚",
		sayName:fun
};

//我们希望调用obj.sayName()时可以输出obj的名字
//obj.sayName();

obj.sayName();

工厂方法创建对象
/*
 * 使用工厂方法创建对象
 * 	通过该方法可以大批量的创建对象
 */
function createPerson(name , age ,gender){
	//创建一个新的对象 
	var obj = new Object();
	//向对象中添加属性
	obj.name = name;
	obj.age = age;
	obj.gender = gender;
	obj.sayName = function(){
		alert(this.name);
	};
	//将新的对象返回
	return obj;
}

/*
 * 用来创建狗的对象
 */
function createDog(name , age){
	var obj = new Object();
	obj.name = name;
	obj.age = age;
	obj.sayHello = function(){
		alert("汪汪~~");
	};
	
	return obj;
}

var obj2 = createPerson("猪八戒",28,"男");
var obj3 = createPerson("白骨精",16,"女");
var obj4 = createPerson("蜘蛛精",18,"女");
/*
 * 使用工厂方法创建的对象,使用的构造函数都是Object
 * 	所以创建的对象都是Object这个类型,
 * 	就导致我们无法区分出多种不同类型的对象
 */
//创建一个狗的对象
var dog = createDog("旺财",3);

构造函数

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

构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写

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

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

构造函数的执行流程:
1.立刻创建一个新的对象
2.将新建的对象设置为函数中this,在构造函数中可以使用this来引用新建的对象
3.逐行执行函数中的代码
4.将新建的对象作为返回值返回

function Person(name , age , gender){
	this.name = name;
	this.age = age;
	this.gender = gender;
	this.sayName = function(){
		alert(this.name);
	};
}
function Dog(){
	
}

var per = new Person("孙悟空",18,"男");
var per2 = new Person("玉兔精",16,"女");
var per3 = new Person("奔波霸",38,"男");

var dog = new Dog();

在Person构造函数中,为每一个对象都添加了一个sayName方法,
也就是构造函数每执行一次就会创建一个新的sayName方法
导致了构造函数执行一次就会创建一个新的方法,

function Person(name , age , gender){
	this.name = name;
	this.age = age;
	this.gender = gender;
	//向对象中添加一个方法
	//this.sayName = fun;
}
//将sayName方法在全局作用域中定义
//将函数定义在全局作用域,污染了全局作用域的命名空间,而且定义在全局作用域中也很不安全
/*function fun(){
	alert("Hello大家好,我是:"+this.name);
};*/

//向原型中添加sayName方法
Person.prototype.sayName = function(){
	alert("Hello大家好,我是:"+this.name);
};

//创建一个Person的实例
var per = new Person("孙悟空",18,"男");
var per2 = new Person("猪八戒",28,"男");
per.sayName();
per2.sayName();

原型 prototype

我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype
这个属性对应着一个对象,这个对象就是我们所谓的原型对象

如果函数作为普通函数调用prototype没有任何作用

当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,
指向该构造函数的原型对象,我们可以通过__proto__来访问该属性

function MyClass(){

}
var mc = new MyClass();
var mc2 = new MyClass();

//console.log(MyClass.prototype);
//console.log(mc2.__proto__ == MyClass.prototype); //true
//console.log(mc.__proto__ == MyClass.prototype); //true

原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,
我们可以将对象中共有的内容,统一设置到原型对象中。当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,
如果没有则会去原型对象中寻找,如果找到则直接使用以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了
使用in检查对象中是否含有某个属性使用对象的hasOwnProperty()来检查对象自身中是否含有该属性
/*
* 创建一个构造函数
*/
function MyClass(){

}

//向MyClass的原型中添加一个name属性
MyClass.prototype.name = "我是原型中的名字";

var mc = new MyClass();
mc.age = 18;

console.log(mc.name);

//使用in检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回true
console.log("name" in mc);


console.log(mc.hasOwnProperty("age"));

console.log(mc.hasOwnProperty("hasOwnProperty"));
原型对象也是对象,所以它也有原型当我们使用一个对象的属性或方法时,会现在自身中寻找,
自身中如果有,则直接使用
如果没有则去原型对象中寻找,如果原型对象中有,则使用,
如果没有则去原型的原型中寻找,直到找到Object对象的原型,
Object对象的原型没有原型,如果在Object原型中依然没有找到,则返回undefined
console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));

console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));

console.log(mc.__proto__.__proto__.__proto__);//null

console.log(mc.hello);

console.log(mc.__proto__.__proto__.__proto__)
toString
function Person(name , age , gender){
	this.name = name;
	this.age = age;
	this.gender = gender;
}
console.log(per.__proto__.__proto__.hasOwnProperty("toString"));//true

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

//当我们直接在页面中打印一个对象时,事件上是输出的对象的toString()方法的返回值
//如果我们希望在输出对象时不输出[object Object],可以为对象添加一个toString()方法
//Person[name=孙悟空,age=18,gender=男]
/*per.toString = function(){
	return "Person[name="+this.name+",age="+this.age+",gender="+this.gender+"]";
};*/

//创建一个Person实例
var per = new Person("孙悟空",18,"男");
var per2 = new Person("猪八戒",28,"男");
垃圾回收 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法 *** 作该对象,
此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收的 *** 作我们需要做的只是要将不再使用的对象设置null即可
var obj = new Object();

//对对象进行各种 *** 作。。。。
obj = null;
内建对象 数组(Array) Date对象 Math 包装类 字符串相关方法 正则表达式 宿主对象 DOM

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/932892.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-17
下一篇 2022-05-17

发表评论

登录后才能评论

评论列表(0条)

保存