简单介绍 JavaScript 的核心语法,作为后续的参考手册。
简介
JavaScript 的核心语法部分相当精简,包括了:A) 基本语法,语言标准的操作符、控制结构、语句等;B) 标准库,对数据结构、算法的封装;C) 宿主环境提供的 API 接口,例如操作浏览器、DOM、WEB 等功能。
如下的代码可以直接在浏览器的 Console 标签页中运行,也可以保存文件中,通常有两个位置,会影响其加载顺序:
- 放在
<head>
中,页面初始化时就会加载。 - 放在
<body>
中,要等页面初始化完成才去加载。
示例如下。
<!DOCTYPE html>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<head>
<title>JavaScript Example</title>
<script>
function displayDate(){
document.getElementById("date").innerHTML=Date();
}
</script>
</head>
<body>
<!-- 标签内部使用 -->
<button type="button" onclick="alert('Hello World!')">Click Me</button>
<br>
<!-- 调用头部的内容 -->
<p id="date">Display Date</p>
<button type="button" onclick="displayDate()">Now</button>
<br>
<!-- 在 Body 中定义 -->
<p id="demo"></p>
<script>
document.getElementById("demo").innerHTML = 15.90;
</script>
</body>
</html>
变量类型
通过 var name = value
定义,在 JavaScript 中,是可变类型,也就是说,变量对应的类型可以随时改变。
var foobar; // undefined
foobar = 5; // 类型为数字
foobar = "Hello World!"; // 类型为字符串
有六种基本类型:字符串 (String)、数字 (Number)、布尔 (Boolean)、空 (Null)、未定义 (Undefined)、Symbol 。其中,Symbol 是 ES6 引入的一种新的类型,标识独一无二的值。
另外,还包含了三种引用数据类型:对象 (Object)、数组 (Array)、函数 (Function) 。
//----- 字符串
foobar = "Hello World!"; // 可以使用单引号或者双引号
foobar = "Hey, I'm Andy."; // 使用双引号内部可以用单引号,反之亦然
//----- 数字
foobar = 123; // 不区分整型、浮点,统一采用64Bits浮点表示
foobar = 3.1415926; // 浮点数
foobar = 1e2; // 科学记数法,也就是100 123e-3 --> 0.123
//----- 布尔
foobar = true; // 只能是真 (true)、假 (false)
//----- 数组
foobar = new Array(); // 可以新建数组然后按照序号赋值
foobar[0] = "Hey";
foobar[1] = 3.1415926;
foobar = new Array("Hey", 3.14);
foobar = ["Hey", 3.14];
//----- 对象
foobar = {name:"Andy", age:10}; // 可以通过 foobar.name 或者 foobar["name"] 访问
而 undefined
是变量声明但未定义时的值,而 null
表示为空值,所以,除了 undefined
null
symbol
这三种特殊类型,就剩下了五种,可以通过如下方式直接声明。
var foobar = new String;
var foobar = new Number;
var foobar = new Boolean;
var foobar = new Array;
var foobar = new Object;
数组
concat()
用于连接两个或多个数组,不会改变现有数组,而是返回连接数组的一个副本。
对象
对象也是最为常用的类型,在定义时比较容易出现歧义,例如 { foobar: 123 }
可以将 foobar
看作代码块中的标签,而 123
作为语句。在定义对象时,最好在大括号外加上圆括号,因为圆括号里只能是表达式,可以确保大括号只能解释为对象,例如 ({ foo: 123 })
。
另外,在对象中可以直接引用变量,变量名就是 Key
而值就是 Value
,如下是一个结合箭头函数的实现。
const addMsg = text => ({
type: "ADD_MSG",
text
})
console.log(addMsg("Hello")); // {type: "ADD_MSG", text: "Hello"}
函数
通过 function
关键字声明一个函数,也可以直接赋值给变量,并且 ...
可以变参(参数收集),数组展开(除了赋值)
//----- 基本函数定义
function foobar() {
alert("Hello World");
}
//----- 使用变量,与上相同
var foobar = function() {
alert("Hello World");
}
另外,在传参数时,还可以使用解构,这样更加简单清晰。简单来说,解构就是可以快速从对象或数组中提取一些值来创建新变量,如下是一个简单的示例。
const person = {firstName: "Andy", secondName: "Dufresne"}
// 正常使用
function dump(person) {
return person.firstName + '-' + person.secondName;
}
dump(person);
// 使用解构传参数
function dump({first, second}) {
return first + '-' + second;
}
dump(person);
箭头函数
在 ES6 中还定义了箭头函数,使的函数定义更加简单,而且关键是 this
就是定义时所指向的对象,而非运行时动态指定,这样代码就很容易理解,如下是几种函数的定义方法。
//----- 箭头函数
var foobar = (a, b) => {
return a * b;
}
//----- 只有一个表达式、返回值
var foobar = (a, b) => a * b;
//----- 只有一个参数、返回值
var foobar = d => d * 2;
//----- 没有参数
var foobar = () => alert("Hello World");
prototype
与传统面向对象的语言 (例如 C++、Java 等) 不同,在 JavaScript 中,除了基础类型外都是对象,包括了函数,即使在 ES6 中引入了类,但也只是语法糖,那么如何将对象联系起来就成了问题,这也就有了原型和原型链的概念。
当谈到继承时,只有对象 (Object) 一种结构,每个对象都有一个私有属性 __proto__
,该属性指向其构造函数的原型对象 (Prototype);而该原型对象同样也有一个自己的原型对象 __proto__
,层层向上直到一个对象的原型对象为 null
。
注意,原型 [[Prototype]]
作为对象的内部属性,无法直接访问,为了方便查看,在 Firefox 和 Chrome 提供了 __proto__
用来访问,不过这个不是非标准的,ECMA 引入了标准原型访问器 Object.getPrototype(object)
。
事件广播
包括了冒泡和捕获两种机制,对于两层嵌套的元素来说,捕获会从外到内传播,冒泡则反之。可以通过 element.addEventListener(event, listener, useCapture)
添加对某个 DOM 元素的事件监听,默认是在冒泡阶段捕获。
常用示例
遍历元素
常见的还有 ById
ByName
等函数,会返回动态 NodeList
数组。
var blocks = document.getElementsByClassName('highlight');
Array.prototype.forEach.call(blocks, function (e) {
... ...
});
新的浏览器还可以使用 querySelector()
querySelectorAll()
函数,相对来说要更简单。其中选择方式可以参考 CSS 选择器 的详细介绍。
document.querySelectorAll(".highlight").forEach(function (e) {
... ...
});
其它
fetch
基本用法为 fetch("url").then(res=>{},err=>{});
,不过第一个 then()
函数中返回的是 Response 对象,但没有真正所需的数据,可通过 json()
函数返回一个 Promise 对象,然后再调用 then()
返回的才是真正所需的数据。
fetch('/v1/user')
.then(res => res.json(), err => { console.log(err) })
.then(data => {
console.log('data is:', data)
}, err => {
console.log(err)
})
也可以在返回的数据中获取 HTTP 头信息。
fetch('/v1/user')
.then(res => {
console.log(res.headers.get('Content-Type'));
return res.json();
}, err => {
console.log(err)
})
日志打印
可以通过 console.log
将一些格式化信息打印到控制台,如下是常用的参数。
%s
字符串。%d
%i
整数。%f
浮点数。%o
%O
object 对象。%c
css 样式,会格式化后面信息。
如下是简单示例。
console.log("%c Hello World", "color:red;font-size:24px;");
console.log("%i %d", 10, 100);
console.log("PI is %f", 3.1415926);
console.log("Hello %s", "World");
console.log("Hello %o", document.body);
console.log("%o", {msg:"hello"});
console.log("%O", {msg:"hello"});
参考
- 一些常见的参考 kangax.github.io ,例如 ES6 兼容性表格 。