JavaScript知识点在框架中的应用
介绍一些重要的JavaScript知识点在框架中的应用, 不完整, 之后再学习到会继续更新.
默认值
1 | //lib1.js |
1 | <body> |
尽管代码分别在三个文件中, 但实际上都处于全局作用域, 等同于:
1 | <body> |
可以将lib2.js
中的代码改为:
window.libraryName = window.libraryName || 'Lib2';
如果全局作用域已经存在libraryName
这个变量且有值, 那么libraryName
的值不会变化, 否则就会被赋值为'Lib2'
在框架中运用这个方法来确定变量名是否在之前已经被使用, 防止其被改变. ES6中引入了const, 也可以解决这个问题, 利用const声明变量, 变量就不可被改变.
创建命名空间
命名空间: 变量和函数的container, 分离具有相同变量名的变量和函数名的函数.
JavaScript中没有命名空间的概念, 因为在JavaScript中, 可以利用对象实现命名空间的功能(faking namespaces).
1 | var greet = 'Hello'; |
不可以直接定义属性的属性:
1 | var english = {}; |
因为点操作符的优先级高于赋值操作符, 关联性是从左到右, 因此会先执行english.greetings, 结果为undefined, 所以会抛出错误. 应该这样做:
1 | var english = {}; |
或者:
1 | var english = { |
参考
函数重载
在Java或C++中有函数重载(function overloading)的概念,即可以定义多个同名函数,但接受不同的参数, 而JavaScript语言中没有这个概念, 因为函数是对象, 所以无法定义多个同名函数, 但因为在JavaScript中函数是一等公民(first class function),可以通过以下方法实现类似的函数重载的功能:
1 | function greet(firstname, lastname, language){ |
Whitespaces
Whitespaces包括回车,制表符,空格.
JavaScript is very liberal about whitespaces, 即使是这样用⬇️, 也完全合理:
1 | var |
在许多框架的源代码中这样的格式十分常见,开发者利用JavaScript引擎对待whitespace的特性将评注性文字以更加可读的形式呈现.
立即调用函数表达式(IIFE)
函数声明不可匿名:
1 | function (name){ |
上面这段代码会抛出错误, 因为语法分析器(Syntax Parser)看到关键词function
之后会认为这是个函数声明, 但函数声明必须有名字,所以会抛出错误. 为了避免这个错误,在function前加上括号, 语法分析器就不会将其解析成函数声明. 括号在JS中是操作符, JS引擎将在括号内的代码都看作表达式.
1 | // 加上括号之后相当于创建了一个函数对象 |
⬆️是函数表达式, 创建之后可以立即调用. 下面是 立即调用函数表达式的几种形式:
1 | var greet = function(name) { |
当图片上这段代码开始执行, JS引擎看到第一行时, 将这部分代码看作函数表达式, 将其作为对象保存在内存空间, 直到执行到('John')
这部分时, 匿名函数(即之前的对象)的执行环境被创建, 匿名函数内的greeting
变量也被保存在这里, 而不是全局环境. 因为这个特点, IIFE在框架中有广泛的应用.
IIFE在框架中的应用:
1 | <script src='greet.js'></script> |
greet.js1
var greeting = 'Hola';
app.js1
2
3
4(function(name){
var greeting = 'Hello';
console.log(greeting + ' ' + name);
}('John'));
上面部分的几段代码执行时相当于:
1 | var greeting = 'Hola'; |
在IIFE中定义的greeting
变量在局部作用域中,不会污染全局作用域的greeting
变量.
如果想在IIFE中使用全局作用域的变量,可在IIFE中声明并传入, 还可在其中改变全局作用域变量的值:
1 | var greeting = 'Hola'; |
工厂函数
1 | function makeGreeting(language) { |
传入外层函数, 在内层函数返回, 尽管在内层函数执行时makeGreeting函数已经跳出执行栈, 但language变量依然存在于内存空间. 调用不同的language, 创造的是不同的执行环境, 因此变量存在于不同的内存空间.
参考