zoukankan      html  css  js  c++  java
  • JS--我发现,原来你是这样的JS(四)(看看变量,作用域,垃圾回收机制是啥)

    一、介绍

    这是红宝书(JavaScript高级程序设计 3版)的读书笔记第四篇,是红宝书第四章内容(主要是变量和作用域问题),当然其中还有我个人的理解。红宝书这本书可以说是难啃的,要看完不容易,挺厚的,要看懂更不容易,要熟练js更是难,中间需要不断的积累与重温。因此不是读一两遍就能把这书吃透,需要多读,可谓温故而知新,可以为师矣。

    同系列:
    第一篇:JavaScript--我发现,原来你是这样的JS(一)(初识)
    第二篇:JavaScript--我发现,原来你是这样的JS(二)(基础概念--躯壳篇,不妨从中文角度看js)
    第三篇:JavaScript--我发现,原来你是这样的JS(三)(基础概念--灵魂篇)

    二、变量

    1 .变量介绍:

    javascript 中的变量是松散型的,既不用去指定改变量的数据类型值,声明变量时直接使用一个操作符var就行。

    //声明变量
    var str = 'string';
    var num = 123;
    //当不用var时,则为全局变量但不推荐这样操作
    i = 123;
    

    2.变量的两种值:基本类型和引用类型的值:

    js的变量有两种不同的数据类型的值:基本类型的值和引用类型的值。

    • 基本类型上一篇提到的五种基本类型:null ,undefined,boolean,string,number
    • 引用类型一般是:对象,函数,数组等,都是object类型
    //基本类型的值
    var num = 123;
    var boo = false;
    //引用类型的值
    var obj = new Object();
    var arr = new Array();
    var arr2 = {};
    

    3.基本类型的值和引用类型的值的区别

    区别一:动态的属性

    动态的属性怎么理解:就是可以动态的增加,删除,改变属性和方法

    • 对于基本类型的值,不能够进行这些操作
    //基本类型的值
    var str = '123';
    //添加属性
    str.age = 123;
    
    console.log(str.age); //undefined,说明该值没被声明,所以基本类型属性没有动态的属性
    
    
    • 对于引用类型的值,能够进行这些操作,例子没毛病
    //引用类型的值
    var person = new Object();
    //添加属性name
    person.name = 'ry-yuan';
    //添加方法sayHi
    person.sayHi = function(){
        console.log('hi');
    }
    
    console.log(person.name);   //输出ry-yuan
    person.sayHi();  //输出hi
    

    区别二:复制变量值不同

    • 对于基本类型变量值之间的复制,会创建一个新值给另一变量,彼此不会相互影响,例子:
    var n1 = 100;
    //n1复制给n2
    var n2 = n1;
    console.log(n2); //100
    //对n2操作自增
    n2++;
    console.log(n1); //100,n1不会受n2影响
    console.log(n2); //101
    
    • 对于引用类型之间复制,则不会创建新值,而是 指向同一个对象
    //引用变量值
    var o1 = new Object();
    //复制o1给o2
    var o2 = o1;
    //为o1添加属性
    o1.name = 'ry-yuan';
    //o2也会有这个属性值
    console.log(o2.name); //'ry-yuan'
    

    为什么引用类型会指向同一个对象?因为o1中存着的值只是一个对象的引用地址,所以o1复制到o2时就把地址复制给o2,两者的地址相同,所以指向同一个对象。

    区别三:传递参数

    这里的传递参数是对函数传递参数。函数参数的按值传递的。传递参数的两者的区别和上面复制的一样。

    • 对于基本数据类型的值,对函数传递参数,是将值复制给函数内部的参数,复制另一份独立的值,所以两者不影响彼此。
    var n = 123;
    function add(num){
        num ++;
        console.log(num);
    }
    
    //将n传给函数add
    add(n);   //124
    console.log(n);  //123,n不会被影响
    
    • 对于引用数据类型的值,对函数传递参数,是将对象在的引用地址值复制给函数内部参数(局部变量),所以操作的是同一个对象。
    //引用类型
    var p = new Object();
    function addName(obj){
        obj.name = 'ry-yuan';
    }
    console.log(p.name);   //undefined,对象没有name属性
    //将p传进函数
    addName(p);  
    console.log(p.name);   //ry-yuan,对象有了name属性
    

    区别四:检测类型

    • 对于基本数据类型,我们使用typeof来确认变量是什么基本数据类型
    var num = 666;
    var str = "hello ry";
    var boo = false;
    var und = undefined;
    var n = null;
    
    console.log(typeof num);  //number
    console.log(typeof str);  //string
    console.log(typeof boo);  //boolean
    console.log(typeof und);  //undefined
    console.log(typeof n);  //object,特别的null返回的是object
    
    • 对于引用类型的值,我们使用instanceof操作符,判断它是什么类型的对象。不用typeof的原因是typeof检测引用类型都会返回object,这不是我们想要的,我们想知道它是什么类型的object
    //这里想知道arr是不是数组类型,如果是返回true,不是返回false
    console.log(arr instanceof Array);
    //这里想知道arr是不是正则类型,如果是返回true,不是返回false
    console.log(arr instanceof RegExp);
    
    
    • 特别的:用instanceof去判断基本类型值都会返回false,因为基本类型数据都不是object,就更不用判断是什么类型的object了。

    三、作用域

    作用域:是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域和局部作用域两种。

    1.全局执行环境:

    最外围的一个执行环境,在web浏览器中,全局执行环境被认为是window对象,因此所有的全局变量和函数都是作为window对象的属性和方法创建的。

    2.局部执行环境:

    局部执行环境是指在函数内部,函数被创建,就会有一个函数作用域,在函数内定义的变量和方法,函数外面不能访问,但函数内可以访问外面的变量和方法。

    //声明一个全局变量,当前最外围是全局作用域
    var g = 1;
    //声明函数fn1
    function fn1(){
    //局部作用域
        //声明一个变量
        var i = 10;    
        //可以访问g
        console.log(g);  //1
        //再声明一个函数fn2
        function fn2(){
        //局部作用域
            var j = 100;
            //可以访问g和i
            console.log(g);  //1
            console.log(i);  //100
        }
        
    //fn1不能访问到fn2里面的变量和方法
    console.log(j);    //报错,j没被定义
    }
    
    //全局作用域中不能访问i,j
    console.log(i);   //报错,i没有被定义
    console.log(j);   //报错,j没有被定义
    
    

    上图:

    全局作用域中只能访问红颜色中有的变量和函数,有g和fn1
    局部作用域fn1中能访问红色+蓝色中的变量和函数,有g,i,fn1,fn2
    局部作用域fn2中能访问整个所有的变量和函数g,i,j,fn1,fn2
    综上越里面的作用域访问的就越多。有种不能渗透到内部,只能向外拓展的感觉。

    3.没有块级作用域

    什么是块级作用域:用大括号括起来的区域{ coding.... }

    js中没有块级作用域,所以有一下这种情况:

    for(var i =0 ; i<10 ; i++){
        console.log(i);
    }
    console.log(i);   //10 ,这里会有结果,i没有被销毁
    

    查询标记符:

    查询标记符怎么操作?
    来个例子:

    var a = 1;
    function getNum(){
        return a ;
    }
    
    console.log(getNum());  //1
    

    我们来分析一下变量a 的查找过程:
    1.首先在getNum函数作用域中找,发现没有a变量
    2.于是向外拓展,到了全局作用域,发现,哎,有a,var了个a,没错就是你了。然后获得这个a。

    再来一个例子:

    var b = 1;
    function get(){
        var b = 2;
        return b;
    }
    console.log(get());  //2
    

    这次又是怎么操作:
    1.在执行函数get时,我们声明了一个b变量,return时需要用到b,这时我们在局部作用域中找,哎,有了,有个b变量,就是你了,然后就返回了。不用再到外面找了。

    4、垃圾回收问题:

    1.什么是js的垃圾回收机制?

    答:javascript中垃圾收集机制是自动回收的,不用人工操作,这让我们更专注于编辑代码上。 回收垃圾机制是定时执行的,具有周期性。

    2.什么时候会有垃圾?

    答:在作用域中当整个作用域中的代码执行完后,作用域中的变量和方法都会没用,此时就是被当做垃圾了。比如局部作用域,一个函数执行完,里面的变量就可以被销毁,其占用内存被释放。

    3.垃圾回收方式?

    答:常用的是标记清除:这样操作:一个变量-->进入环境(被标记,有此标记为不能被清除)-->执行-->离开环境(被标记,这个标记告诉机制能被清除)-->回收机制一段周期后,变量被清除。

    4.为什么还要管理内存?

    答:分配给web浏览器的内存比桌面的应用的内存少,这是出于安全考虑,为了防止运行js的网页耗尽系统内存导致系统崩溃。所以,开发者发现一旦数据不再用时,就将其值设为null来释放其引用(解除引用),这做法适用于全局变量和全局对象属性。

    五、说说

    博文好久没更新啦,堕落了,啊啊啊啊,努力努力,积极向上。最近挺多事。不能挡我学习,通通闪开。

    本文出自博客园:http://www.cnblogs.com/Ry-yuan/
    作者:Ry(渊源远愿)
    欢迎访问我的个人首页:我的首页
    欢迎访问我的github:https://github.com/Ry-yuan/demoFiles
    欢迎转载,转载请标明出处,保留该字段。

  • 相关阅读:
    JDK 14的新特性:更加好用的NullPointerExceptions
    技术回顾系列:最新最热门的技术大事-第一周
    JDK 14的新特性:instanceof模式匹配
    JDK 15 JAVA 15的新特性展望
    怎么break java8 stream的foreach
    java 8 stream中的Spliterator简介
    怎么在java中创建一个自定义的collector
    java 8 stream reduce详解和误区
    java stream中Collectors的用法
    java关于throw Exception的一个小秘密
  • 原文地址:https://www.cnblogs.com/Ry-yuan/p/7675894.html
Copyright © 2011-2022 走看看