1. JavaScript是一门用来与网页交互的脚本语言,包含以下三个组成部分:
- ECMAScript:由 ECMA-262 定义并提供核心功能。
- 文档对象模型(DOM):提供与网页内容交互的方法和接口。
- 浏览器对象模型(BOM):提供与浏览器交互的方法和接口。
2. 将 JavaScript 引入网页,首先要解决它与网页的主导语言 HTML 的关系问题,而将JavaScript插入HTML的主要方法是使用
-
async:可选。表示应该立即开始下载脚本,但不能阻止其他页面动作,比如下载资源或等待其他脚本加载。只对外部脚本文件有效。
-
charset:可选。使用 src 属性指定的代码字符集。这个属性很少使用,因为大多数浏览器不在乎它的值。
-
crossorigin:可选。配置相关请求的CORS(跨源资源共享)设置。默认不使用CORS。crossorigin="anonymous"配置文件请求不必设置凭据标志。crossorigin="use-credentials"设置凭据标志,意味着出站请求会包含凭据。
-
defer:可选。表示脚本可以延迟到文档完全被解析和显示之后再执行。只对外部脚本文件有效。
-
integrity:可选。允许比对接收到的资源和指定的加密签名以验证子资源完整性(SRI,Subresource Integrity)。如果接收到的资源的签名与这个属性指定的签名不匹配,则页面会报错,脚本不会执行。这个属性可以用于确保内容分发网络(CDN,Content Delivery Network)不会提供恶意内容。
-
language:废弃。
-
src:可选。表示包含要执行的代码的外部文件。
-
type:可选。代替 language,表示代码块中脚本语言的内容类型(也称 MIME 类型)。按照惯例,这个值始终都是"text/javascript"。
// 只要创建一个 script 元素并将其添加到DOM 即可。 let script = document.createElement('script'); script.src = 'gibberish.js'; document.head.appendChild(script);
3. 变量
3.1 var
3.1.1 var 声明作用域:使用 var 操作符定义的变量会成为包含它的函数的局部变量,比如使用 var 在一个函数内部定义一个变量,就意味着该变量将在函数退出时被销毁
function test () {
var message = "hi"
}
test()
console.log(message) // 出错
但是,在函数内定义变量时省略var操作符,就会创建一个全局变量:
function test() {
message = "hi" // 全局变量
}
test()
console.log(message) // "hi"
去掉之前的 var 操作符之后,message 就变成了全局变量。只要调用一次函数 test(),就会定义
这个变量,并且可以在函数外部访问到。
注意 虽然可以通过省略 var 操作符定义全局变量,但不推荐这么做。在局部作用域中定
义的全局变量很难维护。
3.1.2 var 声明提升:使用 var 时,下面的代码不会报错。这是因为使用这个关键字声明的变量会自动提升到函数作用域顶部:
function foo() {
console.log(age);
var age = 26;
}
foo(); // undefined
之所以不会报错,是因为 ECMAScript 运行时把它看成等价于如下代码:
function foo() {
var age;
console.log(age);
age = 26;
}
foo(); // undefined
这就是所谓的“提升”(hoist),也就是把所有变量声明都拉到函数作用域的顶部。此外,反复多次
使用 var 声明同一个变量也没有问题:
function foo() {
var age = 16;
var age = 26;
var age = 36;
console.log(age);
}
foo(); // 36
3.2 let:let 跟 var 的作用差不多,但有着非常重要的区别。最明显的区别是,let 声明的范围是块作用域,而 var 声明的范围是函数作用域。
3.2.1 暂时性死区:let 与 var 的另一个重要的区别,就是 let 声明的变量不会在作用域中被提升。
3.2.2 全局声明:与 var 关键字不同,使用 let 在全局作用域中声明的变量不会成为 window 对象的属性(var 声明的变量则会)。
3.2.3 条件声明:在使用 var 声明变量时,由于声明会被提升,JavaScript 引擎会自动将多余的声明在作用域顶部合并为一个声明。因为 let 的作用域是块,所以不可能检查前面是否已经使用 let 声明过同名变量,同时也就不可能在没有声明的情况下声明它。
3.3 const
3.3.1 const 的行为与 let 基本相同,唯一一个重要的区别是用它声明变量时必须同时初始化变量,且尝试修改 const 声明的变量会导致运行时错误。
const age = 26;
age = 36; // TypeError: 给常量赋值3.3 变量 29
// const 也不允许重复声明
const name = 'Matt';
const name = 'Nicholas'; // SyntaxError
// const 声明的作用域也是块
const name = 'Matt';
if (true) {
const name = 'Nicholas';
}
console.log(name); // Matt
3.3.2
const 声明的限制只适用于它指向的变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的属性并不违反 const 的限制。
4. 数据类型
ECMAScript 有 6 种简单数据类型(也称为原始类型):Undefined、Null、Boolean、Number、String 和 Symbol。Symbol(符号)是 ECMAScript 6 新增的。还有一种复杂数据类型叫 Object(对象)。Object 是一种无序名值对的集合。因为在 ECMAScript 中不能定义自己的数据类型,所有值都可以用上述 7 种数据类型之一来表示。
-
"undefined"表示值未定义;
-
Undefined 类型只有一个值,就是特殊值 undefined。当使用 var 或 let 声明了变量但没有初始化时,就相当于给变量赋予了 undefined 值:
-
"boolean"表示值为布尔值;
-
Boolean(布尔值)类型是 ECMAScript 中使用最频繁的类型之一,有两个字面值:true 和 false。这两个布尔值不同于数值,因此 true 不等于 1,false 不等于 0。
-
"string"表示值为字符串;
-
"number"表示值为数值;
-
"object"表示值为对象(而不是函数)或 null;
-
ECMAScript 中的对象其实就是一组数据和功能的集合。对象通过 new 操作符后跟对象类型的名称来创建。开发者可以通过创建 Object 类型的实例来创建自己的对象,然后再给对象添加属性和方法
-
每个 Object 实例都有如下属性和方法。
-
constructor:用于创建当前对象的函数。在前面的例子中,这个属性的值就是 Object()函数
-
hasOwnProperty(propertyName):用于判断当前对象实例(不是原型)上是否存在给定的属性。要检查的属性名必须是字符串(o.hasOwnProperty("name"))或符号。
-
isPrototypeOf(object):用于判断当前对象是否为另一个对象的原型。
-
propertyIsEnumerable(propertyName):用于判断给定的属性是否可以使用
-
toLocaleString():返回对象的字符串表示
-
toString():返回对象的字符串表示。
-
valueOf():返回对象对应的字符串、数值或布尔值表示。通常与 toString()的返回值相同。
-
"null" 类型同样只有一个值,即特殊值 null。逻辑上讲,null 值表示一个空对象指针,这也是给typeof 传一个 null 会返回"object"的原因
-
"function"表示值为函数;
-
"symbol"表示值为符号。