你不知道的JavaScript(上卷)- - 书本知识点记录,前端开发学习

function test(a) {

b = a * 5; // 报错 b没有被定义

let b;

console.log(b);

}


function test(a) {

b = a * 5;

var b; // 正常运行 var会变量提升

console.log(b);

}

console.log(b) // 报错 找不到b


function test(a) {

b = a * 5;

// 正常运行 函数作用域找不到b 就会去外层找

console.log(b);

}

var b;

总结:

  • 如果函数内部找不到 就会往外层找 直到到最外层的Global中

  • 在函数中 就算使用 var 定义的变量 也不会被提升到全局的 Global中,但是还是会变量提升

  • 最好的建议还是使用 let 和 const 因为这里的两个是不会变量提升的,不容易出错

闭包不污染全局变量

function test1() {

var a = 1

}

test1() // 正常运行


(function test2() {})();

test2(); // 报错 找不到 test2这个函数

总结:

  • 正常使用函数确实是可以让函数里面的成员变量私有化,但是函数自己本身是被定义和赋值到全局对象中了,这个或多或少也是一种污染

  • 使用闭包可以解决这个问题,函数变量名被隐藏在自身中意味着不会非必要地污染外部作用域

  • 当函数可以记住并访问所在的词法作用域,即使函数是在当前词法作用域之外执行,这时就产生了闭包。

块作用域

if(true){

var a = 5;

}

console.log(a); // 5


if (true) {

let b = 5;

}

console.log(b); // ReferenceError: b is not defined

总结:

  • 在过去 JS 是没有块级作用域这个概念的,只有函数作用域,因为使用var定义的变量都会被提升到最上面(如果var定义在函数里面也会被提升到函数的最上面)

  • 但是好在ES6推出了let和const关键字,让JS也拥有了块级作用域

变量提升的细节

a = 2;

var a;

console.log( a );

// 编译后的代码

var a;

a = 2;

console.log( a ); // 答案是2


console.log( a );

var a = 2;//浏览器解析到这里 编译器会将这段代码编译成 var a; a = 2; var a会被提到最前面

// 最终经过编译的最终代码是

var a

console.log( a ); // undefined 因为 a只是定义还没有赋值 所以是 undefined

a = 2


foo(); // 不是 ReferenceError, 而是 TypeError!

var foo = function bar() { // … }; // 这里不是函数声明 而是函数表达式

// 编译器处理后

var foo

foo() // TypeError 类型错误 还没声明 foo是函数就使用函数的调用方法

foo = function bar(){}


foo(); // 1

var foo;

function foo() { console.log( 1 ); } // 函数会被提升到最前面,换句话说,函数最先提升

foo = function() { console.log( 2 ); };

总结:

  • 只有声明本身会被提升,赋值和其他的逻辑会留在原地

  • var 和 函数声明都会提升

  • 函数声明会被提升,但是函数表达式却不会被提升

  • 函数会首先被提升,然后才是变量

闭包

function setupBot(name, selector) {

$( selector ).click( function activator() {

console.log( "Activating: " + name );

} );

}

setupBot( “Closure Bot 1”, “#bot_1” );

setupBot( “Closure Bot 2”, “#bot_2” );

// 以上的函数就是一个闭包


function foo() {

var a = 2;

function bar() {

console.log( a );

}

return bar;

}

var baz = foo(); baz(); // 2 —— 朋友,这就是闭包的效果。

总结:

  • 函数是在它本身的词法作用域以外执行。

  • 只要使用了回调函数,实际上就是在使用闭包!

循环和闭包

for (var i=1; i<=5; i++) {

setTimeout( function timer() {

console.log( i );

}, i*1000 );

}

// 结果: 输出5次6

// 因为setTimeout()是一个异步的函数,for循环结束了才会执行setTimeout,而for循环结束的时候 i是等于6的 所以最终会输出5次6

// 因为我们试图在每次循环的时候都能保存下一个i的副本,但是实际上因为作用域,每次都是同一个i,最终i被赋值成了6,所以输出了5次6

解决方案:

for (var i=1; i<=5; i++) {

(function(j) {

setTimeout( function timer() {

console.log( j );

}, j*1000 );

})( i );

}

// 这样就可以解决了, 每次运行的时候都将i存进一个立即执行函数里面,立即执行函数又作用域又可以防治变量污染,就可以解决这个问题了

最优方案:

for (let i=1; i<=5; i++) {

setTimeout( function timer() {

console.log( i );

}, i*1000 );

}

// let 声明,可以用来劫 持块作用域,并且在这个块作用域中声明一个变量

函数的this绑定

this绑定如果分类的话可以分为四类:默认绑定、显示绑定、隐式绑定、new绑定

  • 默认绑定

function demo(){

cconsole.log(this.a)

}

var a = 2

demo() // 2
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

给大家分享一些关于HTML的面试题,有需要的朋友可以戳这里免费领取,先到先得哦。


[外链图片转存中…(img-KAzoUMdc-1712293739912)]

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:前端)

最后

给大家分享一些关于HTML的面试题,有需要的朋友可以戳这里免费领取,先到先得哦。

[外链图片转存中…(img-aydwBSeN-1712293739912)]
[外链图片转存中…(img-C8rJFoVV-1712293739912)]

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值