前端面试准备(十个一组)第一次

181 阅读4分钟

1, let  const  var  区别

let

       语句声明一个块级作用域的本地变量,并且可选的将其初始化一个值;

       允许你声明一个作用域被限制在块级中的变量,语句或表达式

作用域规则

           let声明的变量只在其声明的块或子块中可用;

function varTest() {
     var x= 1;
     {
         var x = 2;
         console.log(x); // 2
     }
     console.log(x); // 2
}


function letTest() {
     let x= 1;
     {
         let x = 2;
         console.log(x); // 2
     }
     console.log(x); // 1

 全局创建变量let  和  var的区别

        let 不会在全局对象里新建一个属性

        var 创建变量,会在全局对象里新建一个属性

var x = 'global';
let y = 'global';

console.log(this.x); // global
console.log(this.y); // undefined 

重复声明  let 和 var

         let 不能重复创建相同的变量 (解析语法不合法)

         var 可以重复创建

暂存死区

         var 初始化前遇到声明的值会初始化为 undefined

         let  初始化前遇到声明的值会报错ReferenceError

functio do_something(){
    console.log(bar); // undefined
    console.log(foo); // ReferenceError
    var bar = 1;
    let foo = 2;
}

暂时死区与typeof

    console.log(bar); // undefined    
    console.log(foo); // ReferenceError    
    console.log(typeof bar); // undefined    
    console.log(typeof foo); // ReferenceError    
    var bar = 1;    
    let foo = 2;

暂时性死区和静态作用域

      在同一行,这个if块中的foo已经在词法中被创建,但没有达到,或终止他的初始化

function test(){
    var foo = 33;
    if(foo){
        let foo = (foo + 55); // ReferenceError
    }
}

暂时性死区 在一种情况

     let n of n.a 已经在for循环块的私有范围内,标识符n.a被解析为位于指令本身 let n中的对象属性a,在没有执行完他的初始化语句,仍旧存在暂时性死区

         function test(n) {            
              console.log(n);           
              for(let n of n.a){ // n ReferenceError               
                  console.log(n);            
              }        
         }        
         test({a:[1,2,3,4]})

正常       
         function test(n,a) {            
              console.log(n);            
              for(let n of a){                 
                   console.log(n);            
              }        
          }        
          test({a:[1,2,3,4]},[1,3,45,])

let 和 var 合并声明

        var 会将变量提升至块的顶部,导致隐式的重复声明变量

let x = 1;

{
   var x = 2; // SyntaxError
}

const 

     常量的块级范围,类似let,不能重新赋值,不能重新声明 暂时性死区

定义数组和对象

不能重新赋值,但是可以改变属性的值,属性值不受保护

const obj = {};
obj = {}; // 报错obj.a = 'p' // 正常

var 

    变量声明,无论在哪声明,都在执行任何代码之前进行处理,用var声明的变量的作用域是他当前执行上下文

声明的变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的

        function x(){            
            y = 1; // 严格模式下会抛出异常            
            var z = 2;        
        }       
        x();       
        console.log(y); // 1        
        console.log(z); // ReferenceError  z未在x外部声明

声明变量在任何代码执行前创建,而非声明变量只有在执行赋值操作的时候才被创建

console.log(a); // ReferenceError   没声明的变量只有在赋值时才被创建
console.log('still go .....'); // still go...

下段代码
var a;
console.log(a); // undefined;
console.log('still go....'); // still go..

声明变量是它所在上下文环境的不可配置属性,非声明变量是可配置的(如非声明变量可以被删除)

var a = 1;
    b = 2;
delete this.a; // 在严格模式下 抛出 TypeError 其他情况下执行失败并无任何提示
delete this.b;
console.log(a,b); // 抛出ReferenceError
// b属性已经被删除

由于上面的几种情况,建议始终定义变量

变量提升

         由于变量声明,总是在任意代码执行前处理,代码中任意位置声明变量总是等效于在代码开头声明,意味着变量可以在声明之前使用,hoisting

bla = 2;
var bla;
// 可以隐式的(implicitly)理解为
var bla;
    bla = 2;
建议在作用域顶部声明变量

给两个变量赋值成字符串

var a = 'A';
var b = a;
等于
var a, b = a = 'A';

赋值的顺序
var x = y,y = 'A';
console.log(x + y); // undefinedA

2,eval

eval() 函数会将传入的字符串当作js代码进行执行

console.log(eval('2+2')); // 4
console.log(eval(new String('2+2'))); // 2+2

   eval是一个危险函数,它是使用与调用者相同的权限执行代码,如果被恶意修改,您最终可能会在您的网页权限下,在用户计算机上运行恶意代码,更重要的是第三方代码可以看到某一个eval被调用的作用域,会导致一些不同方式 的攻击。

eval 通常会比其他替代方法更慢,因为他必须调用js解释器,其他的结构可被现代js引擎进行优化

eval的替代

eval
function looseJsonParse(obj){
    return eval("("+obj+")")}console.log(looseJsonParse("{a:(4-1),b:function(){},c:new Date()}"))

非eval
function looseJsonParse(obj){    return Function('"use strict";return('+obj+')')();}console.log(looseJsonParse("{a:(4-1),b:function(){},c:new Date()}"))