图解Javascript核心内容
成为一个高效的JavaScript开发者的秘诀之一就是真正理解这门语言的语义。本文将会通过通俗易懂的图表来解释JavaScript中最基本的核心内容。
随处可见的引用
简单来说,JavaScript中的变量就是对内存中某个值的引用。这里的值可以是基本类型,如strings, numbers, booleans,也可以是引用类型如objects和functions。
局部变量
下面这个例子中,我们在最上层作用域内创建了四个局部变量,并将它们指向基础类型的值。
1
|
// Let's create some local variables in the top scope
|
2
|
var name = "Tim Caswell" ;
|
3
|
var age = 28;
|
4
|
var isProgrammer = true ;
|
5
|
var likesJavaScript = true ;
|
6
|
// Test to see if the two variables reference the same value
|
7
|
isProgrammer === likesJavaScript;
|
1
|
Output
|
2
|
=> true
|
我们发现这两个布尔类型的变量在内存中指向同一个值。这是因为基础类型的值都是不可变的,所以虚拟机可以优化成让所有的引用都指向同一个值(译者注:为了节省内存开销)。
在上面的代码中我们用恒等号===检查这两个变量的引用是否为同一个值,测试结果为true。
图中黄色矩形代表最上层的作用域。里面的变量是最上层作用域中的局部变量,千万不要与全局对象的属性混淆。
对象与原型链
对象就是拥有对其他对象和原型引用的集合。除此之外,还有唯一特殊的就是原型链,通过原型链,可以访问在局部对象不存在而在其父级对象上的属性。
01
|
// Create a parent object
|
02
|
var tim = {
|
03
|
name: "Tim Caswell" ,
|
04
|
age: 28,
|
05
|
isProgrammer: true ,
|
06
|
likesJavaScript: true
|
07
|
}
|
08
|
// Create a child object
|
09
|
var jack = Object.create(tim);
|
10
|
// Override some properties locally
|
11
|
jack.name = "Jack Caswell" ;
|
12
|
jack.age = 4;
|
13
|
// Look up stuff through the prototype chain
|
14
|
jack.likesJavaScript;
|
1
|
Output
|
2
|
=> true
|
上述代码中,我们把一个有四个属性的对象赋给了变量
tim
,然后又创建了一个继承tim的新对象并赋给变量jack
。接着我们在局部对象中重写了两个属性。
现在当我们要访问jack.likesJavaScript
的时候,首先要在jack引用的对象中查找thelikesJavaScript
属性,如果不存在再去父级对象中查找,最后我们在变量tim引用的对象中找到了这个属性值为true。
全局对象
是不是很想知道为什么像jslint这类工具总是提醒你要在声明变量前加上var
,下面这个例子就很好的解释了原因。
1
|
var name = "Tim Caswell" ;
|
2
|
var age = 28;
|
3
|
var isProgrammer = true ;
|
4
|
// Oops we forgot a var
|
5
|
likesJavaScript = true ;
|
可以发现上述代码中的
likesJavaScript
并不是最上层闭包中的一个自由变量而是全局对象的一个属性。虽然这点只有当你尝试将很多脚本混合在一起的时候才可能遇到麻烦,但是我们还是应该避免在实际开发中出现省略var
的情况。
为了保证变量在当前闭包和它的子闭包内,就要时刻记住在变量声明前加上var
。这条简单的准则,对你有利无害。
如果一定要在全局对象上添加属性,浏览器中,可以像这样添加:window.woo
,在nodejs中,可以像这样添加:global.goo
。
函数和闭包
JavaScript不仅仅是一组链式数据结构。它还有函数(一种可执行、可调用的代码片段)。这些函数形成链式作用域和闭包。
了解闭包
函数可以理解成一种包含可执行代码和属性的特殊对象。每一个函数都有一个 [scope]
属性,这个属性存储着函数在定义时所在的上下文环境。当一个函数返回的时候,其所在的上下文环境就会被销毁,当前上下文也会切换到该函数调用者所在的上下文。
在下面这个例子中,我们创建了一个简单的工厂方法用来生成一个闭包并且返回一个函数。
1
|
function makeClosure(name) {
|
2
|
return function () {
|
3
|
return name;
|
4
|
};
|
5
|
}
|
6
|
var description1 = makeClosure( "Cloe the Closure" );
|
7
|
var description2 = makeClosure( "Albert the Awesome" );
|
8
|
console.log(description1());
|
9
|
console.log(description2());
|
1
|
Output
|
2
|
Cloe the Closure Albert the Awesome
|
当我们调用函数
description1()
的时候,虚拟机查找它引用的函数并执行该函数。该函数执行过程中需要访问名为name
的局部变量,它在闭包作用域中找到了它。当想为每一个生成的函数分配单独的空间存储局部变量的时候,工厂方法是一个非常不错的选择。
可以看看这篇文章why use closure ,将对你深入了解闭包会有很大帮助。
共享函数和THIS
有时候出于性能的考虑,或者仅仅是因为你青睐某种风格,JavaScript提供了一个this
关键字,this
允许你重用一个函数对象,通过不同的调用方式,该对象所在的作用域也不同。
01
|
var Lane = {
|
02
|
name: "Lane the Lambda" ,
|
03
|
description: function () {
|
04
|
return this .name;
|
05
|
}
|
06
|
};
|
07
|
var description = Lane.description;
|
08
|
var Fred = {
|
09
|
description: Lane.description,
|
10
|
name: "Fred the Functor"
|
11
|
};
|
12
|
// Call the function from four different scopes
|
13
|
console.log(Lane.description());
|
14
|
console.log(Fred.description());
|
15
|
console.log(description());
|
16
|
console.log(description.call({
|
17
|
name: "Zed the Zetabyte"
|
18
|
}));
|
1
|
Lane the Lambda Fred the Functor undefined Zed the Zetabyte
|
上述图表中,我们可以看出虽然将
Fred.description
设置成Lane.description
,但依然指向那个函数。因此,这三个引用都拥有那个匿名函数的平等所有权。这就是为什么我尽量不调用构造原型中的方法,因为如果我这么做的话就意味着我将函数绑定到了对象本身和构造函数上。(如果想更加深入的了解this,可以看这篇文章 what is this)
总结
我已经乐此不疲地用图表阐述了这些数据结构。我希望这篇文章能够帮助大家更好的理解JavaScript的精髓。我有过前端开发、后端开发和服务端架构经验。我希望我这种独特的方式能够帮助来自全球各地的开发者更好的了解JavaScript的内部机制。
原文链接/译文链接
图解Javascript核心内容相关推荐
- javascript核心_只需几分钟即可学习这些核心JavaScript概念
javascript核心 Sometimes, you just want to learn something quickly. And reading through comprehensive ...
- ES6/ES2015核心内容-转载
传送门:http://www.cnblogs.com/doit8791/p/5184238.html ECMAScript定义了: JS语言语法 – 语法解析规则.关键字.语句.声明.运算符等. 类型 ...
- 30分钟掌握ES6/ES2015核心内容(上) 1
ECMAScript 6(以下简称ES6)是JavaScript语言的下一代标准.因为当前版本的ES6是在2015年发布的,所以又称ECMAScript 2015. 也就是说,ES6就是ES2015. ...
- 黑马JavaScript核心操作BOM与DOM课程笔记1-DOM
一.Web APIs 简介 此部分的目标:能够说出 Web APIs 阶段与 JavaScript 语法阶段的关联性: 能够说出什么是 API: 能够说出什么是 Web API. 1. Web API ...
- JavaScript核心 DOM 和 BOM操作
JavaScript核心 DOM 和 BOM操作 Web APIs 简介 1. Web APIs 和 JS 基础关联性 1.1 JS 的组成 1.2 JS 基础阶段以及 Web APIs 阶段 JS ...
- JavaScript核心知识第二章---事件高级(含大量代码分析)
前言 ❤️ 一个人有多重的才华,骨子里就会刻上多大重量的谦卑 ❤️ JavaScript核心知识第二章---事件高级 一.JavaScript 事件高级 (1)注册事件(绑定事件) 1.1 注册事件概 ...
- JavaScript核心笔记未完
JavaScript核心 Web API阶段 DOM BOM 操作 js基础是语法阶段 web API阶段是应用 主要是BOM DOM 页面交互功能 1.API 和Web API 1.1API (应用 ...
- JavaScript核心1
JavaScript核心1 Web API阶段 DOM BOM 操作 js基础是语法阶段 web API阶段是应用 主要是BOM DOM 页面交互功能 1.API 和Web API 1.1API (应 ...
- 视频教程-2020年前端面试/晋级必修,60分钟掌握JavaScript核心算法-JavaScript
2020年前端面试/晋级必修,60分钟掌握JavaScript核心算法 十年前端开发经验,熟练掌握vue及react技术栈. 李雄 ¥39.00 立即订阅 扫码下载「CSDN程序员学院APP」,100 ...
最新文章
- 基于RDKit探索DrugBank(demo)
- NBUT校赛 J Alex’s Foolish Function(分块+延迟标记)
- 编程语言里函数方法类型检查的重要性
- lisp中怎样调取图形_越玩越聪明的图形思维游戏
- 多线程的第三种模式(callable)
- tcp 出现rst情况整理
- 玻璃质感_photoshop绘制玻璃质感创意图标
- Navicat Premium 12.1.16.0 安装与激活(图文教程)
- python下载电影链接_Python:输入电影名,爬获取到阳光电影网中对应名称的迅雷下载链接,获取的链接有点问题(具体问题在内容里)...
- 双绞线的制作,T568A线序,T568B线序
- Go语言实用用法大全
- VScode开发PHP的必要插件
- 【cocos源码学习】解决cocos2d-x-4.0 Android Demo构建遇到的问题
- php 插件推荐,Typecho实用插件推荐(一)
- Docker基础入门详解
- Everything研究之快速获取USN记录的文件路径
- Windows 11 手机诞生,还是双屏的?
- 配置 不使用rsa 密码_了解使用RSA的密码学
- 解决Chrome无法从该网站添加应用、扩展程序或脚本
- php结合阿里云(印刷文字识别-身份证识别)进行身份证真实性验证------识别图片中的信息进行验证
热门文章
- 无人机核心技术之运动规划
- 《商用密码应用与安全性评估》第二章政策法规2.2法律法规
- 用 CAReplicatorLayer 创建动画
- Linux专栏5:软件安装和文件结构
- iis服务器的 字体文件, 提示文件或目录不存在,找不到文件
- java荣誉勋章神兵天降_荣誉勋章之空降神兵改良版
- 搜狗输入法怎么变成英文半角
- syzkaller配置小结
- table设置单元格间距
- win10 桌面的的文件都不见了 提示不注销保存都文件都为临时_使用win10不久,C盘只剩下500MB?这样操作,我清理出了30G空间!...