zoukankan      html  css  js  c++  java
  • 来看几段特殊JavaScript的代码(写成这样会被打死)

    1. 12.toString 为什么会报错。

    中间涉及到许多的词法分析,具体可以去看 winter 老师的重学前端、前端进阶训练营,再具体你可以直接去啃 ECMA-262去。

    对于 12.toString 为什么会报错?

    我们来看,我们写一个 NumberLiteral 的时候,有这些写法。

    • 12
    • Number(12)
    • ….

    我们看 ’12.’,还记不记得我们写小数的时候,零点几 我们可以写成 0.12341,也可以写成 .12341。其实在这里,是因为没有对 Number 原型的 prototype 方法的引用,我们写成下面这个样子也就 ok 了。 12. string(),记住中间有一个空格,还有一种方式是 12..toString()

    1. var 声明

      var 声明永远作用于脚本、模块和函数体这个级别,在预处理阶段,不关心赋值的部分,只管在当前作用域声明这个变量。

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

      上面这段代码,函数 foo 成功读取到外部变量 a 的值

      var a = 1;
      
      function foo() {
          console.log(a);	//undefined
          var a = 2;
      }
      
      foo();
      

      很奇怪把,这里是 undefined。这是因为老生常谈的 var 预处理问题。

      这段代码声明了一个脚本级别的 a,又声明了 foo 函数体级别的 a,我们注意到,函数体的 var 出现在 console.log 语句之后。

      但是在预处理过程执行之前,因为有了函数体级别的 a,就不会访问外层作用域中的变量 a 了,而函数体级的变量 a 此时还没有赋值,所以是 undefined。

      var a = 1;
      
      function foo() {
          console.log(a);	// undefined
          if(false) {
              var a = 2;
          }
      }
      
      foo();
      

      这段代码比上一段代码在 var a = 2 之外多了一段 f,我们知道 if(false) 中的代码是永远不会执行的,但是预处理阶段根本不管这个,var 的作用能够穿透一切的structure,它只认脚本、模块还有函数体三种语法结构。所以这里结果跟前一段代码是一样的,我们得到了 undefined。

      3.经典 var 面试题,防止 var 穿透的

      for(var i = 0; i < 20; i++) {
      	var div = document.createElement('div')
      	div.innerHTML = i
      	div.onclick = function() {
      		console.log(i)
      	}
      	document.body.appendChild(div)
      }
      

      这段代码为文档添加了 20 个 div 元素,并且绑定了点击事件,打印它们的序号。但是,实际上,上面的代码点击的时候 console 一直是 20。为什么呢,因为 for 循环的变量 i 会遇到 var 导致的变量提升,然后导致后面的代码console 的 i 会是 for 循环执行完了以后 var 变为 20的 i。

      for(var i = 0;i < 20; i++) {
      	void function(i) {
      		var div = document.createElement('div')
      		div.innerHTML = i
      		div.onclick = function() {
      			console.lgo(i)
      		}
      		document.body.appendChild(div)
      	}(i)
      }
      

      要改变这种情况,我们就使用 IIFE:

      我们通过 IIFE 在循环内构造了作用域,每次循环都产生一个新的环境记录,这样,每个 div 都可以访问到环境中的 i 。

  • 相关阅读:
    Oracle的建表约束
    Sql的增删改操作
    关联查询之92语法和99语法
    日常编程练习(三)
    日常编程练习(二)
    日常编程练习(一)
    C++ 赋值运算符函数
    内存管理
    进程同步——经典的同步问题
    I/O 阻塞与非阻塞,同步与异步
  • 原文地址:https://www.cnblogs.com/ssaylo/p/13157843.html
Copyright © 2011-2022 走看看