最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 一段代码带你论证JS基础[不看后悔篇]

    正文概述 掘金(lin1997)   2020-12-14   329

    一段代码带你论证JS基础[不看后悔篇]

    前言

    JS基础对于我们前端开发的重要性不言而知~于是,我们都会选择去阅读一些书籍来充实自己。那当我们读完那些理论基础之后,你是否依旧迷茫,还是豁然开朗?

    透过现象看本质!

    我想:有了理论基础作为根据的时候,应该多去思考一些代码的结果来实践这些理论。

    就比如解决bug一样,你总得先知道出现bug的原因,再根据原因去解决问题是一样的道理。

    code案例

    var b = 10;
    (function b(){
        b = 20;
        console.log(b); 
    })();
    

    这段代码会输出什么呢?(ps:先别着急回答,好好思考一下)

    乍一看,这段代码很简单,涉及到的内容是var function IIFE,好像也没什么问题。

    这段代码的在严格模式下输出:TypeError: Assignment to constant variable

    意思就是:类型错误:对常量变量的赋值

    而在非严格模式下输出: 一段代码带你论证JS基础[不看后悔篇]

    输出分析

    • 分析严格模式下的输出

    如果由这个TypeError: Assignment to constant variable.做一个分析的话,那么意味着变量b是不可修改的!

    那么现在的问题在于变量b是指外部用var声明的变量b呢,还是立即执行的具名函数b呢?

    如果b是立即执行的具名函数名称,说实话我也不大确定它是否是可修改。(ps:大多数的js书籍中都没有明确指出立即执行函数表达式是否能重新赋值的问题)

    但是我一定可以确定的是,如果b是指外部用var声明的,那么在此代码中它一定是可修改的。我们都知道用var声明的全局变量它在任何地方肯定是可以修改的,因为该变量处于作用域的最顶端。

    所以在这里我想大胆做个假设:变量b是指立即执行的具名函数名称b~

    做完这个假设,我想说:那意味着全局变量b在立即执行的具名函数b里访问不到吗?

    其实不是的,全局变量b在立即执行的具名函数b是可被访问的,只不过因为具名函数b的内部作用域里也存在了一个用function声明的变量b,所以在代码执行的时候js引擎首先找到用function声明的变量b。正如书籍中讲到的作用域查询是通过从里到外向上查询。(ps:之前也顺手写了一篇关于作用域系列的文章:我是这样理解JavaScript中作用域,望能帮助大家~)

    当然在非严格模式下,大家可以试着动手在立即执行的具名函数内部函数打印一下window.b,也可论证全局变量b在立即执行的具名函数b里可被访问! 代码如下:

    var b = 10;
    (function b(){
        b = 20;
        console.log(window.b); 
    })();
    

    到这里,理清楚了立即执行函数b的内部作用域机制,我的疑问又萌生了:为什么(function b(){}())这样的函数表达式就不能修改呢?

    后来,我查阅了资料,明白了IIFE函数的内部机制~

    一段代码带你论证JS基础[不看后悔篇]

    我所理解的是:当遇到具名的函数表达式的时,会创建一个辅助的特定对象,将函数表达式的名称作为唯一的key,用来存储函数表达式的名称,然后添加到函数的作用域链中,该值只读,并且不可以被删除,所以不能对该值进行操作。

    所以,在严格模式下,一个不可修改的常量被修改之后就会报TypeError: Assignment to constant variable.

    • 分析非严格模式的输出

    在非严格模式下会静默失败,所以不报错。针对如上的分析之后,会输出立即执行的具名函数b本身。

    code扩展

    我将代码改写成:

    var b = 10;
    (function b(){
    	return 1;
    })();
    console.log(b); 
    

    那这段又会输出什么呢?

    无论在非严格模式还是在严格模式下,这段代码都会输出10,也就是全局变量b的值~

    写这段代码的本意并不是为了猜测结果而想的,我想表达的是:为什么立即执行具名函数b在外部是不可访问的?难道所有的表达式在外部都不可访问吗?

    为了解决我的疑问,我通过如下函数foo1foo2进行分析:

    //片段1
    var foo1 = function () {};
    console.log(foo1);
    //片段2
    (function foo2(){})
    console.log(foo2);
    
    • 片段1是让一个匿名函数表达式赋值给变量foo1,然后该函数可以用foo1这个名称进行访问——foo1()。所以打印是一个函数。
    • 片段2是一个函数表达式,但结果是Uncaught ReferenceError: foo2 is not defined。说明在外部是不可访问的。

    可见,立即执行具名函数b是一个函数表达式,在外部是不可访问的!(ps:意味着函数表达式既不可能通过名称在函数声明之前调用它,也不可能在声明之后调用它)。

    其实,大多数书籍里介绍以及我之前所理解的片段1这样的代码就是一个函数表达式。但现在我的理解并不是这样的~

    foo1是一个变量,匿名函数表达式赋值给变量foo1了,所以foo1它可被访问!

    通过自己写了2个代码片段,将我的疑惑迎刃而解了~

    思考其他案例

    在闲暇之余,我将最原始的代码块再做了改造,运用这些代码来温故并且思考了之前学习的理论基础。

    如下的代码片段,我将结果也一并和大家揭晓,但我也会和大家分享一下我的心得~

    • 片段1
    var b = 10;
    function b() {
    	console.log(12);
    	return 1;
    }
    console.log(b, b()); //10 TypeError: b is not a function
    

    为什么会打印10呢,而不是函数b呢?

    论据:函数声明优先于变量声明~

    所以,相当于先利用function声明了函数b,再利用var重写了b。

    //片段2
    console.log(b, b()); //12 1
    var b = 10;
    function b() {
    	console.log(12);
    	return 1;
    }
    

    为什么会打印函数b的执行结果12和1呢,而不是全局变量b呢?

    论据:函数声明优先于变量声明~并且在这个过程中存在变量提升。

    • 片段3
    var b = 10;
    b = function() {
    	b = 20;
    	console.log(b); //20
    return 1;
    };
    console.log(b, b()); //b函数,1
    

    为什么会打印10呢,而不是函数b呢?

    论据:这个过程就是将变量b进行重新赋值。

    所以,打印的是10,而不是函数。

    • 片段4
    var b = 10;
    //  Duplicate declaration "b"
    let b = function() {
    	b = 20;
    	console.log(b);
    	return 1;
    };
    

    论据:用var声明变量可以可重复声明,但是用let声明变量不可重复声明。

    所以js引擎要执行完var b = 10语句之后,遇到了let b之前报错了。

    总结

    在写业务代码的时候,要尽量去避免声明变量命名冲突的情况,因为以上案例的的写法是不合理的,很容易出现意想不到的结果。

    为何不规范要求自己而避开不必要的麻烦呢?

    当然,我觉得在学习乏味难啃的理论基础知识时,我觉得应该创造自己的想象力,多去实践多去思考为什么会有这样的结果呢?

    根据理论证实结果!

    这样才会使得让自己更加理解理论基础,并且更好的运用它们,而不仅仅是背/记

    参考资料

    你不知道的JavaScript(上)

    www.cnblogs.com/TomXu/archi…


    起源地下载网 » 一段代码带你论证JS基础[不看后悔篇]

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元