《你不知道的JavaScript》 (上) 阅读摘要
本书属于基础类书籍,会有比较多的基础知识,所以这里仅记录平常不怎么容易注意到的知识点,不会全记,供大家和自己翻阅;
上中下三本的读书笔记:
第一部分 作用域和闭包
第二章 词法作用域
词法查找
全局变量会自动成为全局对象(浏览器中是 window
) 的属性,因此是不可以直接通过全局对象的此法名称,而是间接地通过全局对象属性的应用来对其进行访问 window.a
,通过这种方法可以访问那些被同名变量所遮蔽的全局变量。但是如果非全局的变量如果被遮蔽了,无论如何都无法被访问到。
欺骗词法
如果词法作用域完全由写代码期间函数所生命的位置来定义,那么可以通过几种方法来欺骗(修改)词法作用域,比如 eval
、with
但是要注意:欺骗词法作用域会导致性能下降。
因为JS引擎会在编译阶段进行性能优化,其中有些优化依赖于能够根据代码的词法进行静态分析,并预先确定所有变量和函数的定义位置,才能在执行过程中快速找到标识符。但是如果引擎在代码中找到 eval
、with
,就会完全不做任何优化。
第三章 函数作用域和块作用域
函数作用域
包装函数的声明以 function
关键字开始,那么就是函数声明,而下面这个例子是以 (function
开始,那么就是函数表达式:
const a = 1;
function foo() { // 函数声明
const a = 4;
console.log(a);
}
(function foo() { // 函数表达式
const a = 3;
console.log(a);
}())
console.log(a);
所以上面的 IIFE
将会被当做函数表达式而不是一个函数声明来处理;
函数声明和函数表达式之间最重要的区别是他们的名称标识符会绑定在何处。
函数声明的名称标识符 foo
会被绑定在所在作用域中,可以直接通过 foo()
来调用;而函数表达式的 foo
被绑定在函数表达式只剩的函数中而不是所在作用域中;
同时,即使是具名的函数表达式,名称标识符在赋值之前也无法在所在作用域中使用。
try/catch
结构的 catch
分句中具有块级作用域。
第四章 提升
编译器
函数声明会被提升,而函数表达式不会被提升。
函数优先
函数声明和变量声明都会被提升,但是函数会首先被提升,然后才是变量。
foo() // 1
var foo
function foo() {
console.log(1)
}
foo = function() {
console.log(2)
}
函数声明 foo
会首先被提升,然后打印出 1
,后面的 var
声明会被认为是重复声明而被忽略;但是注意如果后面出现同名函数声明,则会覆盖前面的:
foo() // 2
function foo() { console.log(1) }
function foo() { console.log(2) }
第二部分 this和对象原型
第一章 关于this
this到底是什么
this
实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用,并不是在编写时绑定。当一个函数被调用时,会创建一个执行上下文,它包含函数在哪里被调用(调用栈)、函数的调用方式、传入的参数等信息,this
就是这个记录的一个属性,会在函数执行的过程中用到。
判断this
我们可以根据优先级来判断 this
:
- new 绑定: 函数是否是在
new
中调用,如果是的话,this
绑定的是新创建的对象;var bar = new foo()
- 显式绑定: 函数是否通过
call
、apply
或者硬绑定调用,如果是的话,this
绑定的是指定的对象;var bar = foo.call(obj)
- 隐式绑定: 函数是否在某个上下文对象中调用,如果是的话
this
绑定的是那个上下文对象;var bar = obj.foo()
- 默认绑定: 如果都不是的话,在严格模式下绑定到
undefined
,非严格模式绑定到全局对象;var bar = foo()
例外
- 被忽略的情况: 比如把
null
、undefined
作为this
的绑定对象传入call
、apply
、bind
,那么这些值在调用时会被忽略,实际应用的是默认绑定; - 箭头函数: 箭头函数根据外层作用域来决定
this
,且箭头函数的绑定无法被修改,new
也不可以;
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android Parcelable接口使用方法详解
- 假期结束了,撸一篇技术和大伙分享下吧!
- Android AIDL实现跨进程通信的示例代码
- Android中SharedPreferences简单使用实例
- 功能强大的Android滚动控件RecyclerView
- Android使用 Retrofit 2.X 上传多文件和多表单示例
- Android状态栏白底黑字的示例代码
- Android使用ViewPager实现顶部tabbar切换界面
- Android 中ScrollView与ListView冲突问题的解决办法
- Android数据库操作工具类分享
- Android使用RadioGroup实现底部导航栏
- Android 中Fragment与Activity通讯的详解
- Android常用控件ImageSwitcher使用方法详解
- Android实现阅读进度记忆功能
- Android 控制ScrollView滚动的实例详解