前言:在此专栏中将会讲到 js 基础性的知识,包括但不仅限 es5、es6。将知识点与实际应用相结合,从理解到开发。每一次学习都有所收获,每一次重温知识点都加深印象,每一次掌握一种新知识都像打开了新世界的大门。希望在自己学习的同时能够帮助更多的人学习和理解。同时也欢迎各位猿友提出宝贵的建议和交流,有不对的地方还请赐教。
一. 开门见山
基本上每种语言的语法都有相似之处,学过一种那么其他的语法都好理解。在这里不过多地介绍语法相关知识,为了能够让小白中的小白也能理解,个别地方会详细说明。
1.使用
作为一种灵活性很高的解释型脚本语言,JavaScript 可以使用
script
标签引入并在标签内写方法,可以使用export
import
exports
在各个模块间相互引用。
1)script
可以通过script
标签的src
属性引入 js 文件,可以在script
标签内部书写 js 代码。
- script 标签在 html 界面中按自上而下的顺序依次执行,如果其中一个在加载中,其它文件需要等待其加载完再加载,如果 script 引入文件数量较多且体积较大,那么将会影响界面的渲染效果比如样式的渲染。所以一般将 script 放置 body 末尾。
- script 标签内部的 js 代码没有异步操作的情况下按照书写顺序执行
- script 标签可以跨域,也就是耳熟能详的
jsonp
(其他跨域标签之后统一讲解)
2)export
es6 中可以使用export default
导出模块,如:export default 666
3)import
es6 中可以使用import A from B
引入模块,可以使用import {a} from B
引入变量
4)exports
在 commonjs 中使用exports.default
导出模块,使用 require(‘xxx’),由于 nodejs 早年间也借鉴了 commonjs 模块化思维,所以在 nodejs 中导出也类似,比如使用module.exports
导出模块,使用 require 引入模块。
2.变量
js 遵循的是 ECMAScript 标准,而 ECMAScript 标准中的变量是松散类型的,所以先学习了其他语言比如 c 语言、Java 的同学第一眼可能觉得不可思议,因为 var 既可以定义数字、数组还可以定义字符串。
-
声明
es5 中定义使用 var(读音“哇~”),es6 中使用 let。 -
变量提升
es5 中变量可以重复声明,执行顺序是先声明后初始化,所有声明语句会被提到作用域最顶端先执行,导致变量出现提升。
var a = 0;
console.log(a); //0
console.log(b); //undefined
var b = 9;
在这里 b 变量就发生了提升,真正执行的顺序是:
var b;
console.log(b);
b = 9;
也就是说在打印的时候 b 还没有值,只是声明了并没有定义值。
如果打印的是不存在的没有声明的值则抛出异常not defined
来做一个题目测一下有没有看懂:
var a = 10;
function foo() {
console.log(a);
var a = 5;
console.log(a);
}
foo();
上面的代码执行结果:
var a = 10;
function foo() {
console.log(a); // undefined
var a = 5;
console.log(a); // 5
}
foo();
这段代码真正的执行顺序是:
var a;
a = 10;
function foo() {
var a;
console.log(a);
a = 5;
console.log(a);
}
foo();
如果这里看懂了,那么就理解了变量提升。
es6 中使用 let
声明变量不会产生变量提升,而且变量不能重复声明。
console.log(b); // err not defined
let b = 10;
let b = 5; // err has already been declared
- 局部变量、全局变量
js 在 es5 中没有绝对的私有属性和私有方法,所以要注意对变量的处理。
这里的局部和全局是以函数为界限,在使用 var 声明的情况下,在函数外声明的为全局变量,函数内声明的为局部变量。
var a = 5; // 全局
function foo() {
var a = 6; // 局部
var b = 7; // 局部
}
foo();
console.log(a); // 5
console.log(b); // err not defined
在没有使用 var 声明的情况下为全局变量。
var a = 5;
function foo() {
a = 6;
b = 7;
}
foo();
console.log(a); // 6
console.log(b); // 7
这里函数内部没有用 var 声明的变量把函数外的变量值覆盖了,如果有多层嵌套的函数,没有 var 的变量会一直往外查找声明,直至找到并替换。
es6 新增了const
可以声明常量,使用 const 声明的变量名不能重复值不能被覆盖。
3.函数
es5 中函数可以通过function
关键字声明一个函数(函数声明),也可以像声明变量一样使用 var 来声明(函数表达式)。
- 声明式函数、表达式函数
function foo(){ // 声明
...
}
var foo = function(){ // 表达式
...
}
表达式函数也会产生变量提升。
es6 中可以舍去 function 关键字来定义函数,但是需要在 {} 语块内,例如:
class Test {
foo(){
...
}
}
- 匿名函数
匿名函数一般出现在回调函数里,比如:
setTimeout(function(){
...
},1000)
setTimeout(()=>{
...
},1000)
- 构造函数
构造函数是指用来创建初始对象的方法,总与new
操作符一起使用。比如原生的构造函数Object
Array
。
function Person(name, age) {
this.name = name;
this.age = age;
}
var person = new Person("zhangsan", "22");
console.log(person.name); // zhangsan
构造函数可以用来创建特定类型的对象,在实现 js 继承的时候用得比较多。这个后期讲。
- 闭包
闭包就是能够访问另一个函数作用域中变量的函数,最常见的就是一个函数里面写了另外一个函数:
function foo() {
var b = 12;
function too() {
// 闭包
console.log(b);
}
}
4.作用域
es5 中没有块级作用域,也就是说如果在一个作用域里面声明了一个变量,在作用域外也能访问。最典型的栗子:
for (var i = 0; i < 10; i++) {
console.log(i); // 0,1,2...
}
console.log(i); // 10
常见的模拟块级作用域的处理方法是使用匿名立即执行函数:
(function() {
for (var i = 0; i < 10; i++) {
console.log(i);
}
})();
console.log(i); // i is not defined
在 es6 中增加了块级作用域,使用 let 声明:
for (let i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // i is not defined
总结:以上总结了一些 js 常见基本,包括有变量、函数、作用域。可以掌握到的知识有变量提升、局部变量全局变量、作用域,模拟块级作用域和块级作用域。