js学习知识点总结(二)

1、 js中var、let、 const声明变量说明

常见面试问题

eg1:var的使用,浏览器控制台上会打印什么?

var a = 10;
function foo() {
console.log(a); // ??
var a = 20;
}
foo();

解析如下:

上面的语句等同于下述语句

var a = 10; // 全局使用域
function foo() {
// var a 的声明将被提升到到函数的顶部。
	 var a;
    console.log(a); // **打印 undefined**,由于仅仅声明了变量,
// 实际初始化值20只发生在这里
	a = 20; // local scope
}

eg2:如果我们使用 let 或 const 代替 var,输出是否相同?

var a = 10;
function foo() {
console.log(a); // ??
let a = 20;
}
foo();

解析如下:

let和const声明可以让变量在其作用域上受限于它所使用的块、语句或表达式。与var不同的是,这些变量没有被提升,并且有一个所谓的暂时死区(TDZ)。试图访问TDZ中的这些变量将引发ReferenceError,因为只有在执行到达声明时才能访问它们。

var a = 10; // 全局使用域
function foo() {
    // TDZ 开始
// 创建了未初始化的'a'
    console.log(a); // ReferenceError
// TDZ结束,'a'仅在此处初始化,值为20
let a = 20;
}

下表概述了与JavaScript中使用的不同关键字声明的变量对应的提升行为和使用域:
js学习知识点总结(二)_第1张图片

js中的箭头函数“ => ”使用总结

详细介绍可以参考原文:原文链接,重要

箭头函数 是在es6 中添加的一种规范

x => x * x 相当于 function(x){return x*x}

箭头函数相当于 匿名函数, 简化了函数的定义。

箭头函数有两种格式:

  • 一种只包含一个表达式,没有{…} 和 return 。
  • 一种包含多条语句, 这个时候{} return 就不能省略
x => {
     if (x>0){
         return x*x
     }else{
        return x
     }
}

如果有多个参数就要用():

// 两个参数返回后面的值
(x, y) =>x*y + y*y
//没有参数
() => 999
// 可变参数
(x, y, ...rest) =>{
    var i,sum = x+y;
    for (i=0;i<rest.length;i++){
        sum += rest[i];
    }
    return sum;
}

如果要返回一个单对象, 就要注意, 如果是单表达式, 上面一种会报错, 要下面这种

// **这样写会出错**
x => {foo:x} // 这和函数体{}有冲突
// 写成这种
x => {{foo:x}}

箭头函数 看起来是匿名函数的简写。但是还是有不一样的地方。 箭头函数中的this是词法作用域, 由上写文确定

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function () {
            return new Date().getFullYear() - this.birth; // this指向window或undefined
        };
        return fn();
    }
};

箭头函数修复了this的指向, this 总是指向词法作用域, 也就是外层调用者obj:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象
        return fn();
    }
};
obj.getAge(); // 25

如果使用箭头函数,以前的那种hack写法 就不需要了:
var that = this;

由于this 在箭头函数中已经按照词法作用域绑定了, 所以施一公call 或者apply() 调用函数的时候, 无法对this 进行绑定, 即 传入的第一个参数被忽略:

var obj={
    birth:2018,
    getAge:function(year){
    var b =this.birth;//2018
    var fn = (y)=>y-this.birth //this.birth 仍然是2018
    return fn.call({birth:200},year)
}
}
obj.getAge(2020)

常见面试问题

eg1:“newArray”中有哪些元素?

var array = [];
for (var i = 0; i < 3; i++) {
    array.push(() => i);
}
var newArray = array.map(el => el());
console.log(newArray); // ??  [3, 3, 3]

解析如下:
在for循环的头部声明带有var关键字的变量会为该变量创建单个绑定(存储空间)。 阅读更多关于闭包的信息。 让我们再看一次for循环。

// 误解作用域:认为存在块级作用域
var array = [];
for (var i = 0; i < 3; i++) {
// 三个箭头函数体中的每个`'i'`都指向相同的绑定,
// 这就是为什么它们在循环结束时返回相同的值'3'。
    array.push(() => i);
}
var newArray = array.map(el => el());
console.log(newArray); // [3, 3, 3]

如果使用 let 声明一个具有块级作用域的变量,则为每个循环迭代创建一个新的绑定。

// 使用ES6块级作用域
var array = [];
for (let i = 0; i < 3; i++) {
// 这一次,每个'i'指的是一个**新的的绑定,并保留当前的值**。
// 因此,每个箭头函数返回一个不同的值。
    array.push(() => i);
}
var newArray = array.map(el => el());
console.log(newArray); // [0, 1, 2]

解决这个问题的另一种方法是使用闭包。

let array = [];
for (var i = 0; i < 3; i++) {
    array[i] = (function(x) {
return function() {
return x;
        };
    })(i);
}
const newArray = array.map(el => el());
console.log(newArray); // [0, 1, 2]

注释:

//关于下述语句的理解
var newArray = array.map(el => el());

可以使用 map(…) 来把一个函数的列表变形为一个它们返回值的列表:

var one = () => 1;   //其中的one 、 two、three实则是函数对象哦,类似于函数名
var two = () => 2;
var three = () => 3;

[one,two,three].map( fn => fn() );
// [1,2,3]

你可能感兴趣的:(js基础知识,js基础,js复习知识点)