1 写在前面

以下内容大纲

  • JS运行机制
  • 栈内存
  • 堆内存
  • 思考题
  • 判断语句 & 三元运算符 & switch
  • 相等 & 绝对相等

2.1.5 JS运行机制

问题:

var a = 12;
var b =a;
b = 13;
console.log(a);        =>12

var obj1 ={n:100};
var obj2 =obj1;
obj2.n = 200;
console.log(obj1.n); =>200

浅分析JS的运行机制

  • 当浏览器(内核/引擎)渲染和解析JS时,会提供一个供JS代码运行的环境,我们把这个环境称之为“全局作用域”(global/window scope)
  • 代码自上而下执行(之前还有一个变量提升阶段)

栈内存

本身就是一个提供JS代码执行的环境

所有的基本类型值都会直接点再栈内存中开辟一个位置进行存储

基本数据类型的值会存储在当前作用域之下

  • var a = 12;
  1. 首先开辟一个空间存储12

  2. 再当前作用域中声明一个变量a (var a)

  3. 让声明的变量和存储的12进行关联(把存储的12赋值给a, 赋值操作叫定义)

    基本数据类型(也叫做值类型),是按照值来操作的:把原有的值复制一份放到新的空间或者位置上,和原来的值没有关系

图片说明

堆内存

用来存储引用类型中的信息值

​ 对象存储的是键值对

​ 函数存储的是代码字符串

引用数据类型的值不能直接存储在当前作用域之下(因为存储内容过于复杂),我们需要先开辟一个新的空间(理解为仓库)把内容存储在这个空间

  • var obj1 = {n:100};

    1. 首先开辟一个新的内存空间,把对象的键值对一次存储起来(为了保证后面可以找到空间,此空间有一个16进制地址)
    2. 声明一个变量
    3. 让变量和空间地址关联一起(把空间地址赋值给变量)
  • 引用类型不是按值操作,它操作空间地址:把原来的空间地址赋值给新的变量,但原来的空间没有被克隆,还是一个空间,这样就会出现多个变量关联的是相同的空间,相互之间就会存在影响

图片说明
图片说明

思考题1

/*
*1.形成一个全局作用域(栈内存)
2.代码自上而下执行
    1)首先开辟一个新的堆内存(AAAFFF111),吧键值对存到堆内存
        n:10
        m:obj.n*10    =>obj.n此时堆内存信息还没有存储完成,空间地址没有给obj,此时obj是undefined,此时obj.n<=>undefined.n
*/
var obj = {
    n:10,
    m:obj.n*10    =>//Cannot read property 'n' of undefined
};
console.log(obj.m);

总结:注意,是先有值,后有对象

思考题2

var ary1 = [3,4];
var ary2 = ary1;
ary2[0] = 1; // =>ary1 = [1,4]
ary2 = [4,5];    
ary2[1] = 2;     //=>ary2=[4,2]
ary1[1] = 0;    //=>ary1 = [1,0]
console.log(ary1,ary2);

图片说明

2.1.6 JS中的判断语句

1、if / else if / else

var num = 12;
if(num>10){
    num++;
}else if(num>0 && num<10){
    num--;
}else{
    num+=2;
}
console.log(num);


if(0){
   //在JS中只有"0/NaN/空字符串/null/undefined"这五个值转换为布尔类型为false
   }

if('3px'+3){
   //在JS中,+ - * /都是数***算,除 + 意外,其余运算符都在运算的时候,如果遇到了非数字类型的值,首先会转换为数字类型(Number),然后在进行运算

    // + 在JS中除了数学相加,还有字符串拼接作用(如果运算中遇到字符串,则拼接,否则数学相加)

    // > <都是数学比较,非数字比较都是先转换(Number)为数字
   }

问题1

var num = parseInt('width:35.5px');        //=>num = NaN
if(num==35.5){
    alert(0);
}else if(num==35){
    alert(1);
}else if(num==NaN){
    alert(2);
}else if(typeof num=='number'){
    //先算typeof num
    //在比较
    alert(3);    //alert输出的都是字符串的'3‘
}else{
    alert(4);
}

typeof (逻辑运算符?)

用来检测数据类型方式之一,除此之外还有:

  • instanceof (逻辑运算符)
  • constructor (方法)
  • Object.prototype.toString.call() (方法)
//语法
//typeof [value]
typeof 12 =>number

//返回值:使用typeof检测出来的结果是字符串,字符串包含着对应的数据类型,例如:"string"/"number"/"object"/"boolean"/"undefined"/"function"

typeof null => "object" 因为null代表空对象指针(没有指向任何内存空间
typeof 检测数组/正则/对象最后都返回的是"object",也就是基于这种方式无法细分对象

console.log(typeof []);
=>"object"

console.log(typeof typeof [])
=>"string"

2.1.7 三元运算符 & switch

语法:条件?成立事件:不成立事件;

var num = 12;
if (num>10){
    num++;
}else{
    num--;
}
//=>三元运算符     num>10?num++:num--;
//特殊

1、如果三元运算符某一部分不需要任何处理,用null/undefined/void 0...占位即可
num>10?num++:null;
num>10?num++:void 0;
num>10?num++:undefined;

2、如果需要执行多项任务,用小括号包起来
num=10;
bum>10?(num++,num*10):null;

Switch

  1. 加break,不加会顺序后延,且后面条件全部执行
  2. default等价于else
  3. 每一次case的比较都是===“绝对相等”
let a = 10;
switch(a){
    case 1:
        console.log('hh');
        break;
    case 2:
        console.log('hh');
        break;
    default:
        console.log('hh');
}

//在a=1/2事都执行console.log('hh');
//不加break可以实现变量在某些值之下做相同的事情
switch(a){
    case 1:
    case 2:
        console.log('hh');
        break;
    default:
        console.log('hh');
}

思考题:

let a = '1';
switch(a){
    case 1:
        console.log('hh');
        break;
    case 2:
        console.log('xx');
        break;
    default:
        console.log('dd');     //=>输出'dd' 每一次case的比较都是===“绝对相等”
}

if(a == 1){
    console.log('hh');        //=>输出'hh'
}else{
    console.log('dd');
}

== VS ===

==:相等(如果左右两边数据类型不同,是默认转换为相同的类型,然后比较)

'5'==5 =>true

===:绝对相等(类型不一样肯定不相等,不会转换为相同数据类型)

'5'===5 =>false