深入JS 之 面试官经常问的 THIS 闭包 let\const\var 你会了吗?

8.关于this指向的题目分析

    1. 给元素的某个事件行为绑定方法【DOM0 & DOM2】,当事件行为触发,方法执行,方法中的this是当前元素本身
box.onclick = function(){}; //DOM0
box.addEventListener('click',function(){}) //DOM2

// IE 6~8
box.attachEvent('onclick',function(){}) //方法执行里面的this是window
复制代码
    1. 函数执行,看前面是否有点’.’
    • @1 有点 ‘.’前面是谁,this就是谁
    • @2 没有点 方法中的this是window(非严格模式)/undefined(严格模式)
    1. 箭头函数中没有自己的this,箭头函数执行,没有初始化this这个步骤,用到的this都是其上级上下文中的this

废话少说直接上题目

  • 以下代码作为运行示例
var x = 3, 
    obj = { 
        x:5 
    }; 
obj.fn = (function(){ 
    this.x *= ++x; 
    return function (y) { 
        this.x *= (++x) + y; 
        console.log(x); 
    } 
})() 
 
var fn = obj.fn; 
obj.fn(6) 
fn(4) 
console.log(obj.x, x)
复制代码

THIS指向分析.png

  • 以下代码作为运行示例
var num = 10;
var obj = {
    num: 20
};
obj.fn = (function (num) {
    this.num = num * 3;
    num++;
    return function (n) {
        this.num += n;
        num++;
        console.log(num);
    }
})(obj.num);
var fn = obj.fn;
fn(5);
obj.fn(10);
console.log(num, obj.num);
复制代码

this分析-1.png

  • 分析以下代码
let obj = {
    fn: (function () {
        return function () {
            console.log(this);
        }
    })() //obj.fn = function (){console.log(this)}把自执行函数执行的结果‘小函数’ 赋值给obj.fn
};
obj.fn(); // obj 
let fn = obj.fn;
fn(); //window
复制代码
  • 分析以下代码
var fullName = 'language';
var obj = {
    fullName: 'javascript',
    prop: {
        getFullName: function () {
            return this.fullName;
        }
    }
};
console.log(obj.prop.getFullName()); //this -> obj.prop    obj.prop.fullName => undefined
var test = obj.prop.getFullName;
console.log(test()); //this -> window  window.fullName => 'language'
复制代码
  • 分析以下代码
var name = 'window';
var Foo = {
    name: "Foo",
    show: function () {
        console.log(this.name);
    },
    wait: function () {
        var fun = this.show;
        fun();
    }
};
Foo.wait();
//this -> Foo  fun = Foo.show()  fun() this -> window 'window'
复制代码
  • 分析以下代码
window.val = 1;
var json = {
    val: 10,
    dbl: function () {
        this.val *= 2;
    }
}
json.dbl();
// this -> json   json.val = json.val * 2 = 10 * 2 = 20
var dbl = json.dbl;
dbl();
// this -> window  window.val = window.val * 2 = 1 * 2 = 2
json.dbl.call(window);
// this -> window  window.val = window.val * 2 = 2 * 2 = 4
alert(window.val + json.val);
// 4 + 20 => // '24'
复制代码
  • 分析以下代码
(function () {
    var val = 1;
    var json = {
        val: 10,
        dbl: function () {
            val = val * 2; 
        }
    };
    json.dbl();
    // this -> json  val = 1 * 2 = 2 上级上下文 中的val
    alert(json.val + val); // 10 + 2 = 12  => '12'
})();
复制代码

9.关于闭包的分析

废话少说直接上题目

  • 1.以下代码作为运行示例
let x = 5;
function fn(x) {
    return function (y) {
        console.log(y + (++x));
    }
}
let f = fn(6);
f(7);
fn(8)(9);
f(10);
console.log(x); 
复制代码

闭包的分析1.png

    1. 以下代码作为运行示例
let a = 0,
    b = 0;
function A(a) {
    A = function (b) {
        alert(a + b++);
    };
    alert(a++);
}
A(1);
A(2);
复制代码

闭包的分析2.png

10.关于let、const、var的区别

    1. let VS var
    • @1 var存在变量提升,而let不存在变量提升
    console.log(x) //undefined
    console.log(y) //Uncaught ReferenceError: Cannot access 'y' before initialization
    var x = 12
    let y = 13
    // const fn = function () {}; //函数表达式(没有变量提升,只能在创建函数以下使用);用const声明,后期不允许重构fn;「推荐」
    复制代码
    • @2 全局上下文基于var声明的变量是直接存储到GO中的(window),而let是存储到VO(G)中的,和GO没关系
    var x = 12;
    let y = 13;
    console.log(x,y); //12 13
    console.log(window.x, window.y)//12 undefined
    复制代码
    • @3 var允许重复声明(只不过浏览器只声明一次而已,但是词法上是允许的);但是let在词法上,都不允许重复声明[错误发生在”词法解析阶段”],并且不论我们基于何种方式声明过这个变量(例如:var/function再或者是一个形参…)再基于let/const声明都会报错
    var x = 12
    var x = 13
    console.log(x); //13
    let x = 15  //Uncaught SyntaxError: Identifier 'x' has already been declared
    复制代码
    • @4 在JS代码执行的过程中,如果大括号(排除对象和函数)中出现let/const/function/class等关键词(切记:没有var),则大括号所在的代码块,会产生一个“私有块级上下文”!! var不会产生块级上下文,而且块级上下文对他也没有任何的作用!!
    console.log(a) //undefined
    console.log(b)//Uncaught ReferenceError: Cannot access 'b' before initialization
    var a = 12
    let b = 13
    if(1 == 1){
      /*
      EC(BLOCK) 块级私有上下文
      VO(BLOCK) 私有变量对象
        b ----> 200
        a ----> 100
      作用域链:<EC(BLOCK),EC(G)> 上级上下文:是看在哪执行代码产生的块级上下文
      初始化THIS 没有这一步 块级上下文中没有自己的THIS 用到的THIS都是上级上下文中的
      初始化ARG 没有这一步
      形参赋值 没有这一步
      变脸提升 var a
      代码执行
      */
      console.log(a) //12
      console.log(b) //Uncaught ReferenceError: Cannot access 'b' before initialization
      var a = 100
      let b = 200
      console.log(a) //100
      console.log(b) //200
    }
    console.log(a) //100
    console.log(b) //13
    复制代码
    • @5 暂时性死区
    console.log(x); //Uncaught ReferenceError: x is not defined 使用未被声明的变量,结果应该是报错的
    console.log(typeof x); //“undefined” 基于typeof检测一个未被声明的变量,结果是“undefined”,而不会报错!!
    
    
    //-------------------------------------------------------
    console.log(typeof x); //Uncaught ReferenceError: Cannot access 'x' before initialization
    let x = 12; //使用let 声明后在声明之前使用是会报错的
    复制代码
    1. let VS const
    • let 和 const 声明的都是变量,都是要存储到当前上下文的VO/AO变量对象中的
    • @1 let声明的变量,后续根据需求,可以改变‘变量’和‘值’之间的指针指向;而const不允许改变“变量”的指针指向;
    let a = 12
    a = 13
    console.log(a) //13
    
    const a = 12
    a = 13; // Uncaught TypeError: Assignment to constant variable..
    const obj = {
      name: 'zhangsan'
    };
    obj.name = 'lisi';
    console.log(obj); //{name:'lisi'}
    复制代码
    • @2 const 声明的变量必须要有初始值
    let n
    console.log(n) //undefined
    const m ; //Uncaught SyntaxError: Missing initializer in const declaration
    复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享