zoukankan      html  css  js  c++  java
  • JS变量+作用域

    基本类型-栈内存

    保存基本类型的变量保存的是值本身


    引用类型-堆内存

    保存引用类型的变量保存的并不是对象本身,而是一个指向该对象的引用地址


    引用类型判断对象是否相等

        function equalObjs(a, b) {
            for (var p in a) {
                if (a[p] !== b[p]) return false;
            }
            return true;
        }
        console.log(equalObjs(xm, xh));

    引用类型判断数组是否相等

        function equalArrays(a, b) {
            if (a.length !== b.length) return false;
            for (var i = 0; i < a.length; i++) {
                if (a[i] !== b[i]) return false;
            }
            return true;
        }

    引用类型对象复制(浅拷贝:只拷贝一层)

        function copyObj(obj) {
            var newObj = {};
            for (var p in obj) {
                newObj[p] = obj[p];
            }
            return newObj;
        }
    console.log(undefined==null); /*true*/
    console.log(undefined===null); /*false*/

    从一个变量向另一个变量复制引用类型的值,复制的其实是指针,因此两个变量最终都指向同一个对象,当给变量赋新值时,此变量就不再指向原来的对象了;

    数组是引用类型的 , 如题中b=a相当于a与b指向同一个地址 , 但是a=[4,44]之后改变了a的地址 , 所以b不会受到影响 为[4] . 后面又把a=b指向了同一个地址 ,此时为b添加元素 , 因为a、b的地址都没有改变 ,a也会随之改变 ,所以a为[4,44] . 


    参数传递的本质是值的复制,由于person是引用类型,这里就相当于把person的地址复制给了函数setName的参数obj

        function setName(obj) {
            obj.name = 'xm';
            obj = {};
            obj.name = 'xh';
        }
        var person = {};
        setName(person);
        console.log(person.name); /*xm*/
        obj = person

    检测变量类型typeof

        console.log(typeof 4);//number
        console.log(typeof(4));//number
        console.log(typeof 'str');//string
        console.log(typeof true);//boolean
        console.log(typeof undefined);//undefined
        console.log(typeof null);//object
        console.log(typeof []);//object
        console.log(typeof {});//object
        console.log(typeof function () {});//function
        console.log(typeof /a/);//object

    instanceof检测引用类型

    不能检测基本数据类型,只要是基本数据类型和instanceof连用,返回的都是false

        console.log([] instanceof Array);//true
        console.log([] instanceof Object);//true
        console.log({} instanceof Object);//true
        console.log({} instanceof Array);//false
        console.log(1 instanceof Number);//false
    console.log(null instanceof Object);//false

    有两个变量,分别是a = {name: 'xm'}, b = [4],我们不用第三个变量来调换a和b的值

        var a = {name: 'xm'}, b = [4];
        a=[a,b];
        b=a[0];
        a=a[1];

    作用域与解析机制

    全局变量容易被污染,少用

    with(obj)可以延长作用域链,但不推荐使用

        var person = {};
        person.name = 'xm';
        person.sex = 'male';
        var score = 4;
        
        with(person) {
            name = 'xh';
            sex = 'female';
            score = 44;
        }
        console.log(person.name);
        console.log(person.sex);
        console.log(score);

    有3个按钮给每个按钮添加点击事件,希望每次点击时输出当前点击的是第几个按钮,但是目前不论点击哪个按钮,最终输出的都是4

    原因:由于先绑定,后触发,给每个按钮绑定事件,但是在触发的时候i已经是循环完之后,i的值了

    (1)单击方法导致的循环问题。提示:单击方法在循环外面定义

    (2)在循环中调用,并将被点的按钮的型号传进去

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        <title>变量、作用域</title>
        
    </head>
    <body>
        <button>1</button>
        <button>2</button>
        <button>3</button>
        <script type="text/javascript">
            // 错误代码
            var btns = document.getElementsByTagName('button');
                for (var i = 0; i < 3; i++) {
                    btns[i].onclick = function () {
                    alert(i + 1);
                };
            }
    
            //正确代码
            var btns = document.getElementsByTagName('button');
            var fn=function(i){
                btns[i].onclick=function(){
                    alert(i+1);
                }
            }
            for(var i=0;i<btns.length;i++){
                fn(i);
            }
        </script>
    </body>
    </html>

    不存在的变量或函数会报错;不存在的属性或方法,返回undefined;||是短路操作,形如a||b,如果a的值转换成布尔值是true的话,a||b等于a;如果a的值转换成布尔值是false的话,a||b等于b

            console.log(person||(person='xm'));
            console.log(window.person||(window.person='xm'));

    预解析

    1. 以var 声明的变量 会预解析 ,赋值为undefined;没有var则不进行预解析
    2. 以let 声明的变量 不会进行预解析 
    3. 函数的声明会预解析 , 函数会被提升,然后从上到下执行代码的时候,输出fn,就是提升的函数
    4. 函数表达式不进行预解析


    案例1:

    (1)      预解析:外层查找var,name和age为undefined

    (2)      预解析:内层函数fn,函数在预解析时,已经提前进行了该函数的声明。函数内变量argument、name、age为undefined

    (3)      正常执行:外层name从undefined变为’xm’,age从undefined变为18

    (4)      正常执行:内层输出name为undefined

    (5)      正常执行:内层name从undefined变为’xh’,age从undefined变为10

        var name = 'xm';
        var age = 18;
        function fn(argument) {
            console.log(name); //undefined
            var name = 'xh';
            var age = 10;
        }
        fn();

    如果预解析时变量名与函数名重复,那么只预解析函数

    案例2:

        console.log(a);
        var a = 1;/*var预解析之后是undefined*/

    案例3:

        console.log(a);
        a = 1;/*没有预解析,报错*/

    案例4:

        console.log(a); //预解析结果a()
        var a = 1;
        console.log(a); //正常赋值后执行1
        function a() {
            console.log(2); //函数在预解析之后不再解析
        }
        console.log(a); //1
        var a = 3;
        console.log(a); //3
        function a() {
            console.log(4);
        }
        console.log(a); //3
        a(); //报错,此时a=3,不是函数

    案例5:

    函数内部没有var,不进行预解析。输出时查找外层a,输出1;赋值时对外层a进行操作

        var a = 1;
        function fn() {
            console.log(a);
            a = 2;//修改全局变量a
        }
        fn();
        console.log(a);

    案例6:

    函数参数也相当于var定义的局部变量,预解析为undefined。赋值时对参数a进行操作

        var a = 1;
        function fn(a) {
            console.log(a);
            a = 2;/*对参数a进行操作,从undefined变为2,全局变量a没有改变*/
        }
        fn();
        console.log(a);

    案例7:

    函数参数也相当于var定义的局部变量,预解析为undefined。赋值时对参数a进行操作

        var a = 1;
        function fn(a) {
            console.log(a);//将全局变量赋值给参数,因此参数输出1
            a = 2;//将参数从1变成2,全局变量没有改变
        }
        fn(a);//执行时将全局变量a=1传入参数
        console.log(a);//1

    垃圾收集机制

    解除变量引用的方法是将其设置为null

  • 相关阅读:
    webapi 获取json数据
    js的匿名函数与自定义函数
    深入理解计算机系统 第八章 异常控制流(2)
    深入理解计算机系统 第八章 异常控制流(1)
    深入理解计算机系统 第三章 程序的机器级表示(2)
    深入理解计算机系统 第三章 程序的机器级表示(1)
    深入理解计算机系统 第二章 信息的表示和处理(2)
    深入理解计算机系统 第二章 信息的表示和处理(1)
    深入理解计算机系统第一章,计算机系统漫游
    Leetcode练习(Python):第292题:Nim 游戏:你和你的朋友,两个人一起玩 Nim 游戏:桌子上有一堆石头,每次你们轮流拿掉 1
  • 原文地址:https://www.cnblogs.com/chenyingying0/p/12142217.html
Copyright © 2011-2022 走看看