- 基本类型值(值类型) VS 引用类型值
var n=10;
var m=n;
m=20;
console.log(n); //=>10
var a={name:'珠峰'};
var b=a;
b.name='培训';
console.log(a.name); //=>'培训'
var n=[12,23,34];
var m=n;
m[0]=100;
m=[100];
n[1]=200;
console.log(n,m);//=>n:[100,200,34] m:[100]
var obj={
n:10,
m:obj.n*10
};
console.log(obj.m);
====
创建变量并且赋值的详细操作步骤
例如:var n = 10;
- 变量提升阶段(js代码执行之前),第一步先把n这个变量声明 var n;(默认值undefined)
- 开辟一个位置或者空间,把值存储起来
- 让变量和值关联在一起(基于等号完成赋值),我们把赋值关联这一步称之为“变量的定义”
注意点:
- 当我们的值还没有彻底准备完成之前,值和变量是没有关系的
====
【基本类型操作机制 =>值类型】
值类型操作都是“按照值来操作的”
- 赋值的时候,也是直接的把这个值赋值给变量(或者说和变量关联)
- 一个变量把自己的值赋值给另外一个变量的时候,也是重新开辟一个新的位置,把原有变量存储的值放到新位置一份(新老位置各有相同的值,但是是独立分开的,没有关联),在把新位置上的值赋值给新变量
- …
====
【引用数据类型】
引用数据类型,操作的时候,都是按照“空间的引用地址来操作的”
- 首先不能像基本基本值一样在作用域中开辟位置存储,需要额外单独开辟一个新的空间(有一个16进制的地址,通过地址可以找到空间)
- 对于对象数据类型来说,它会把自己本身的键值对依次存储到这个空间中(对于函数来说,在空间中存储的是函数体中的代码字符串)
- 引用类型是按照引用地址来操作的,所以给变量赋的值是空间的地址,而不是对象本身,以后的操作都是通过地址找到空间然后再操作
====
【堆占内存】
在JS中有两个重要的内存:堆内存/栈内存
- 栈内存
- 提供代码执行的环境
- 基本类型值都是直接的存储在栈内存中的
- 堆内存
- 引用类型值都存储在堆内存中
===========================
二、DOM操作
在JS中通过一系列属性和方法,可以操作页面中的元素标签等
- 想要操作谁,就先获取谁
- 按照自己的需求,使用对应的API(提供的属性和方法)操作即可
【获取元素】document.getElementById
:在整个文档中,通过ID获取到指定的元素对象(这里document是限定了获取元素的范围,我们把它称为执行上下文(context))
[context].getElementsByTagName
:在指定的上下文中,通过标签名获取一组元素(获取的一组元素称之为 元素集合(HTMLCollection))
====================
三、ECMAScript中的操作语句
【判断语句】
- if / else if / else
var n = parseFloat('width:15.5px'); //=>NaN
if(n==15){
console.log(1);
}else if(n==15.5){
console.log(2);
}else if(n==NaN){ //=>NaN!=NaN
console.log(3);
}else if(typeof n=='number'){ //=>typeof NaN : "number"
console.log(4);
}else{
console.log(5);
}
- 三元运算符
处理简单的if/else
var n=10;
if(n>=10){
n++; //<=>n=n+1 n+=1 自身累加1
}else{
n--;
}
//=>改写成三元运算符
n>=10?n++:n--;
//=====================
var m=10;
if(m>=10){
m++;
console.log(m);
}
m>=10?(num++,console.log(m)):null;
如果某一部分不需要做任何的事情,我们不写东西,语法不符合,我们可以使用null/udnefined/void 0来占位即可
如果某部分需要做多件事情,我们用小括号包裹起来,每一句中间用逗号分隔即可
思考题:
var n=10;
if(n>=0){
if(n<=10){
n++;
}else{
n--;
}
}else{
if(n<=-10){
n++;
}
}
回去后改写成三元运算符
- switch case
应用于一个变量在不同值情况下的不同操作
var n=10;
if(n==5){
n++;
}else if(n==10){
n+=2;
}else{
n+=3;
}
//=>改写
switch(n){
case 5:
n++;
break; //=>当前情况成立,结束判断,不在向下找
case 10:
n+=2;
break;
default:
n+=3;
}
每一种CASE情况的比较都是基于“===”绝对相等完成的
'10'==10 =>true 相等比较,不严格,如果等号两边的数据类型不相同,则转换为相同的在进行比较
'10'===10 =>false 绝对相等,一定要保证类型和值都相等才可以,类型不一样,不会转换,直接不等
======
数学运算符:+ - * / %(取余)
在JS中“+”有特殊的含义,其它运算符都是数学运算(如果操作的值不是数字,也会先转换为数字,然后在运算)
'3'-1 =>2
'3px'-1 =>NaN
“+”在JS中不仅仅是数学运算,也有字符串拼接的效果(只要运算中出现字符串,就是字符串拼接,否则就是数学运算)
3+1 =>4
'3'+1 =>'31'
'3px'+1 =>'3px1'
【循环语句】
- for循环:在JS中如果我们想按照一定的规律重复去做某件事情,则需要使用循环
var ary = [12,23,34,45];
//=>需求:获取数组中的每一项(数组长度不固定)
for(var i=0;i<ary.length;i++){
console.log(ary[i]);
}
/*
* i=0 i<4 第一轮循环
* console.log(ary[0]);
* i++ -> i=1
* i=1 i<4 第二轮循环
* console.log(ary[1]);
* i++ -> i=2
* ...
* i=4 i<4 循环结束
*/
任务:回去后自己查询(建议百度搜索、也可以看视频)break和continue在for循环中的作用和细节问题
==================================
四:ECMAScript中的函数(function)
函数:一个方法,基于方法可以实现一些功能 函数诞生的目的在于“封装”:把实现功能的代码封装到一个函数中,以后再想实现这个功能,不需要重新编写代码,只需要执行函数即可,这样降低了页面中的冗余代码,提高了代码的重复利用率(“低耦合高内聚”)
function 函数名([形参]){
函数体:实现功能的JS代码
}
函数名([实参]);
//=>创建函数
function fn() {
var n = Math.PI;
n *= 100;
n = n.toFixed(2);
console.log(n);
}
//=>执行函数
fn();
fn();
fn();
...
函数的运作机制:
【创建函数】
- 函数也是引用类型值,首先开辟一个新的堆内存(16进制地址)
- 把函数体中实现功能的代码“当做字符串”存储到堆内存中
- 把堆内存的引用地址赋值给函数名(变量名)
【执行函数】
目的:把函数体中的JS代码执行,以此实现具体的功能和需求
- 首先开辟一个新的栈内存(私有作用域),提供JS代码执行赖以生存的环境
- 把原有在堆内存中存储的“字符串”,拿过来,放到新的栈内存中,变为真正的JS代码,自上而下执行
====
封装一个函数实现一些功能,有时候发现实现功能的原材料不足,需要执行函数的时候传递给我们才可以,此时我们可以给函数设置几个入口,我们把函数的入口称之为:“形参变量”(入口是变量)
//=>创建一个函数实现两个数求和
function sum(n,m){
//=>n/m就是形参入口,也是两个变量
var total=0;
total=n+m;
console.log(total);
}
//=>执行函数
sum(10,20); //=>传递的值是实参(实参是传递给形参变量的具体值) n:10 m:20
sum(10); //=>n:10 m:undefined 设置了形参,执行的时候不传递值,默认值是undefined
sum(10,20,30); //=>n:10 m:20