快速掌握JavaScript面试基础知识(二)
译者按: 总结了大量JavaScript基本知识点,很有用!
为了保证可读性,本文采用意译而非直译。另外,本文版权归原作者所有,翻译仅用于学习。

根据StackOverflow调查, 自2014年一来,JavaScript是最流行的编程语言。当然,这也在情理之中,毕竟1/3的开发工作都需要一些JavaScript知识。因此,如果你希望在成为一个开发者,你应该学会这门语言。
这篇博客的主要目的是将所有面试中常见的概念总结,方便你快速去了解。(鉴于本文内容过长,方便阅读,将分为三篇博客来翻译, 此为第二部分。第一部分请点击快速掌握JavaScript面试基础知识(一))
闭包
闭包由一个函数以及该函数定义是所在的环境组成。我们通过例子来形象解释它。
function sayHi(name){
|
请理解var sayHiToJon = sayHi('Jon');这行代码的执行过程,sayHi函数执行,首先将message的值计算出来;然后定义了greeting函数,函数中引用了message变量;最后,返回greeting函数。
如果按照C/Java语言的思路,sayHiToJon就等价于greeting函数,那么会报错:message未定义。但是在JavaScript中不一样,这里的sayHiToJon函数等于greeting函数以及一个环境,该环境中包含了message。因此,当我们调用sayHiToJon函数,可以成功地将message打印出来。因此,这里的闭包就是greeting函数和一个包含message变量的环境。(备注: 为了便于理解,此段落未按照原文翻译。)
闭包的一个优势在于数据隔离。我们同样用一个例子来说明:
function SpringfieldSchool() {
|
在elementary被创建的时候,SpringfieldSchool已经返回。也就是说staff无法被外部访问。唯一可以访问的方式就是里面的闭包函数getStaff和addStaff。
我们来看一个面试题:下面的代码有什么问题,如何修复?
const arr = [10, 12, 15, 21]; |
上面的代码输出的结果全部都一样:”The value undefined is at index: 4”。因为所有在setTimeout中定义的匿名函数都引用了同一个外部变量i。当匿名函数执行的时候,i的值为4。
这个问题可以改用IIFE(后面会介绍)方法来解决,通过对每一个匿名函数构建独立的外部作用域来实现。
const arr = [10, 12, 15, 21]; |
当然,还有一个方法,使用let来声明i。
const arr = [10, 12, 15, 21]; |
立即调用的函数表达式(Immediate Invoked Function Expression)(IIFE)
一个IIFE是一个函数表达式在定义之后立即被调用。常用在你想对一个新声明的变量创建一个隔离的作用域。
它的格式为: (function(){....})()。前面的大括号用于告诉编译器这里不仅仅是函数定义,后面的大括号用于执行该函数。
var result = []; |
使用IIFE可以:
- 为函数绑定私有数据
- 创建一个新的环境
- 避免污染全局命名空间
环境(Context)
我们往往容易将环境(Context)和作用域(Scope)搞混,我来简单解释一下:
- 环境(Context): 由函数如何被调用而决定,往往指
this。 - 作用域(Scope): 可访问的变量。
函数调用:call, apply, bind
这三个方法都是为了将this绑定到函数,区别在于调用的方式。
.call()会立即执行函数,你需要把参数按顺序传入;.apply()会立即执行函数,你需要把所有的参数组合为一个数组传入;
.call()和.apply()几乎相同。哪个传入参数方便,你就选择哪个。
const Snow = {surename: 'Snow'}
|
注意:如果你将数组传入call函数,它会认为只有一个参数。
ES6允许使用新的操作符将数组变换为一个序列。
char.knows.call(Snow, ...["nothing", "Jon"]); // You know nothing, Jon Snow |
.bind()返回一个新的函数,以及相应的环境和参数。如果你想该函数稍后调用,那么推荐使用bind。.bind()函数的优点在于它可以记录一个执行环境,对于异步调用和事件驱动的编程很有用。
.bind()传参数的方式和call相同。
const Snow = {surename: 'Snow'}
|
this关键字
要理解JavaScript中this关键字,特别是它指向谁,有时候相当地复杂。this的值通常由函数的执行环境决定。简单的说,执行环境指函数如何被调用的。this像是一个占位符(placeholder),它指向当方法被调用时,调用对应的方法的对象。
下面有序地列出了判断this指向的规则。如果第一条匹配,那么就不用去检查第二条了。
new绑定 - 当使用new关键字调用函数的时候,this指向新构建的对象。function Person(name, age) {
this.name = name;
this.age =age;
console.log(this);
}
const Rachel = new Person('Rachel', 30); // { age: 30, name: 'Rachel' }显示绑定(Explicit binding) - 当使用
call或则apply的时候,我们显示的传入一个对象参数,该参数会绑定到this。 注意:.bind()函数不一样。用bind定义一个新的函数,但是依然绑定到原来的对象。function fn() {
console.log(this);
}
var agent = {id: '007'};
fn.call(agent); // { id: '007' }
fn.apply(agent); // { id: '007' }
var boundFn = fn.bind(agent);
boundFn(); // { id: '007' }隐式绑定 - 当一个函数在某个环境下调用(在某个对象里),
this指向该对象。也就是说该函数是对象的一个方法。var building = {
floors: 5,
printThis: function() {
console.log(this);
}
}
building.printThis(); // { floors: 5, printThis: function() {…} }默认绑定 - 如果上面所有的规则都不满足,那么
this指向全局对象(在浏览器中,就是window对象)。当函数没有绑定到某个对象,而单独定义的时候,该函数默认绑定到全局对象。function printWindow() {
console.log(this)
}
printWindow(); // window object
注意:下面的情况中,inner函数中的this指向全局。
function Dinosaur(name) {
|
- 词法(Lexical) this - 当是使用
=>来定义函数时,this指向定义该函数时候外层的this。 备注:大概是和定义的词法(=>)有关,把它称作Lexical this。
function Cat(name) {
|
严格(Strict)模式
如果你使用了"use strict"指令,那么JavaScript代码会在严格模式下执行。在严格模式下,对于词法分析和错误处理都有特定的规则。在这里我列出它的一些优点:
- 使得Debug更容易:以前会被忽略的错误现在会显示报错,比如赋值给一个不可写的全局变量或则属性;
- 避免不小心声明了全局变量:赋值给一个未定义的变量会报错;
- 避免无效使用delete:尝试去删除变量、函数或则不可删除的属性会抛出错误;
- 避免重复的属性名和参数值:对象上重复的属性和函数参数会抛出错误(在ES6中不再是这样);
- 使得
eval()更加安全:在eval()中定义的变量和函数在外部作用域不可见; - “安全”的消除JavaScript中this的转换:如果
this是null或则undefined不在转换到全局对象。也就是说在浏览器中使用this去指向全局对象不再可行。
对于在严格(strict)模式和测试阶段都没有发现的bug,不妨接入线上实时监控插件Fundebug。
版权声明:
转载时请注明作者Fundebug以及本文地址:
https://blog.fundebug.com/2018/01/22/the-definitive-javascript-handbook-for-a-developer-interview-2/
快速掌握JavaScript面试基础知识(二)的更多相关文章
- 快速掌握JavaScript面试基础知识(三)
译者按: 总结了大量JavaScript基本知识点,很有用! 原文: The Definitive JavaScript Handbook for your next developer interv ...
- 快速了解JavaScript的基础知识
注释 单行注释: // 单行注释 多行注释: /* 多行 注释 */ 历史上 JavaScript 可以兼容 HTML 注释,因此 <!-- 和 --> 也可以是单行注释. x = 1; ...
- javascript的基础知识及面向对象和原型属性
自己总结一下javascript的基础知识,希望对大家有用,也希望大家来拍砖,毕竟是个人的理解啊 1.1 类型检查:typeof(验证数据类型是:string) var num = 123; cons ...
- java 基础知识二 基本类型与运算符
java 基础知识二 基本类型与运算符 1.标识符 定义:为类.方法.变量起的名称 由大小写字母.数字.下划线(_)和美元符号($)组成,同时不能以数字开头 2.关键字 java语言保留特殊含义或者 ...
- 菜鸟脱壳之脱壳的基础知识(二) ——DUMP的原理
菜鸟脱壳之脱壳的基础知识(二)——DUMP的原理当外壳的执行完毕后,会跳到原来的程序的入口点,即Entry Point,也可以称作OEP!当一般加密强度不是很大的壳,会在壳的末尾有一个大的跨段,跳向O ...
- Dapper基础知识二
在下刚毕业工作,之前实习有用到Dapper?这几天新项目想用上Dapper,在下比较菜鸟,这块只是个人对Dapper的一种总结. 2,如何使用Dapper? 首先Dapper是支持多种数据库的 ...
- 快速掌握Docker必备基础知识
快速掌握Docker必备基础知识 Docker是时下热门的容器技术,相信作为一名开发人员,你一定听说过或者使用过,很多人会把Docker理解为一个轻量级虚拟机,但其实Docker与虚拟机(VM)是两种 ...
- python基础知识(二)
python基础知识(二) 字符串格式化 格式: % 类型 ---- > ' %类型 ' %(数据) %s 字符串 print(' %s is boy'%('tom')) ----> ...
- JavaScript 之基础知识
JavaScript 基础知识 JavaScript 是属于网络的脚本语言! JavaScript 被数百万计的网页用来改进设计.验证表单.检测浏览器.创建cookies,以及更多的应用. JavaS ...
随机推荐
- JavaScript工作体系中不可或缺的函数
一.函数的概念 日常生活中,我们要完成一件事,总是习惯先有一个计划,后期按照计划,一步一步执行,则能够完成,并且达到一定效果实现一定的功能.在编程的世界里,“功能”可称呼为“函数”,因此“函数”即一段 ...
- Android NDK学习(一):目录结构解析
我们配置好NDK环境后,基本可以看到其目录结构如下图: 下面我们来分析一下NDK根目录的结构: ndk-build:该Shell脚本是Android NDK构建系统的起始点,一般在项目中仅仅执行这一个 ...
- Oneinstack 环境安装 Flarum 轻量级论坛程序
之前做了个论坛,使用的是discuz框架,虽然这个框架已经很成熟,功能也相对较多,但毕竟老框架了,今天尝试用Flarum来搭建一个论坛,Flarum相对来说美观而且速度快 系统环境使用oneinsta ...
- IntelliJ IDEA 的下载和安装
下载 官网地址:https://www.jetbrains.com/idea/ 直接点击 DOWNLOAD 下载 接下来跳转到一个页面,可以看到第一个红框中是选择操作系统的,IDEA分为收费的旗舰版和 ...
- JVM内存分配和垃圾收集策略
java内存区域 程序计数器 因为java可以多线程并发执行,因此,为了线程切换后能恢复到正确的执行位置,每个线程都需要一个独立的程序计数器.记录正在执行的虚拟机字节码指令的地址. 这个区域不会产生内 ...
- Mysql实现树形递归查询
最近在做项目迁移,Oracle版本的迁到Mysql版本,遇到有些oracle的函数,mysql并没有,所以就只好想自定义函数或者找到替换函数的方法进行改造. Oracle递归查询 oracle实现递归 ...
- Java 11 正式发布,这 8 个逆天新特性教你写出更牛逼的代码
美国时间 09 月 25 日,Oralce 正式发布了 Java 11,这是据 Java 8 以后支持的首个长期版本. 为什么说是长期版本,看下面的官方发布的支持路线图表. 可以看出 Java 8 扩 ...
- python之N阶乘结果末尾有几个0
算法思路:首先是算阶乘,可以使用内置函数reduce实现,其次是计算结果的末尾有几个0,可以使用除余判断 代码如下: #!/usr/bin/env python#-*-coding:utf-8-*- ...
- 设置Firefox(火狐)浏览器的中文菜单/界面
步骤一: 设置Firefox浏览器的中文菜单/界面.首先需要查一下正在使用的火狐版本号(小生使用的火狐版本是55.0.3). 步骤二: 下载对应版本的xpi中文插件 其次,访问下面的火狐官方 ...
- ES6躬行记(10)——正则表达式
在ES5中,如果使用构造函数RegExp()初始化RegExp对象(即正则表达式),并且它的第一个参数是正则表达式时,那么不允许再传入标志字符串(即第二个参数).而ES6更改了这项限制,如果传入了第二 ...