# 开始

# 介绍、注释及基本输出方式

# JavaScript 注释

JavaScript 的注释与 JAVA 几乎相同,单行注释以 // 开头,在其后添加注释。多行注释以 / 开头,以 / 结尾,在中间添加注释。

/************** 函数名:getAbsolute******************/  
/************** 功能:求一个整数的绝对值 **************/  
/************** 作者:Bruce*************************/  
/************** 时间:2018 年 2 月 1 日 *******************/  
function getAbsolute(a) {  
    if(a < 0) {  
      a = -a;// 取 a 的相反数  
    }  
    return a;  
}

# 输出

# 第 1 种:弹出对话框模式

通过 alert () 函数弹出对话框,这是最常用的方式。在 script 标签下,调用 window.alert () 函数,括号内填入输出的内容。将下面的代码以文本编辑器编辑后改为 .html 后缀,然后用浏览器打开后即可弹出对话框。

<!DOCTYPE html>  
<html>  
    <body>  
        <script>  
        window.alert("Hello,World!");  
        </script>  
    </body>  
</html>

以浏览器方式打开刚刚建立的 HTMl 文件,在浏览器上面可以看到,如图 1 所示

# 第 2 种:控制台模式

通过 console 输出到控制台,在 script 标签下,调用 console.log () 函数,括号内填入输出的内容,以浏览器打开下面的代码后,按 F12 键即可在浏览器的控制台中实现输出。

<!DOCTYPE html>  
<html>  
    <body>  
        <script>  
        console.log("Hello,World!");  
        </script>  
    </body>  
</html>

除此之外,还有 console.error ()、console.warn () 等方式实现输出,分别表示输出错误,输出警告。

# 第 3 种:页面输出模式

通过 document.write () 实现输出到页面。在 document.write () 函数的括号中填入输出的内容即可。例子如下:

<!DOCTYPE html>  
<html>  
    <body>  
        <script>  
        document.write("Hello,World!");  
        </script>  
    </body>  
</html>

浏览器的页面输出如图 3 所示:

# JavaScript 与 HTML

什么是 HTML
HTML,即超文本标记语言,是一种用于编写网页的脚本语言,超文本,包括图片、视频、音频等非文本元素,这些元素要在网页上展示就离不开 HTML。目前,网站后台开发的语言和框架多种多样,前端却基本围绕着如何丰富 HTML 这个基础而发展。
作为一门编程语言,HTML 的内容很多,可以参考我们的 HTML 相关实训,这里仅介绍 HTML 代码的结构。
由尖括号对和括号内文字构成的整体被称为标签,两个匹配的标签构成标签对,匹配指两个标签的文字相同,后者文字前加入 / 符号, <body></body> 即一个标签对。标签之间可以嵌套。
HTML 代码所有内容在 <html></html> 标签对之间,下层又分为两个标签对 <head></head><body></body> ,后者中间放入网页内容的主体部分。

使用内置 script 标签对的方式嵌入 JS 代码
将 JavaScript 嵌入到 HTML 中有两种方法,对于内容较少的 JavaScript 代码,常采用将 JavaScript 代码直接写在 HTML 中的做法。
<script></script> 之间写入 JavaScript 代码,然后将标签连同代码放入到 <head></head> 或者 <body></body> 之间,常见的是放在 <head></head> 之间,因为这样 JavaScript 和 HTML 的主体内容相对分开,便于阅读。如下是一个实例:

<!DOCTYPE html>  
<html>  
    <head>  
        <script>  
        console.log("在HTML中嵌入JavaScript,这里是JS部分");  
        </script>  
    </head>  
    <body>  
    <!-- 这里是 HTML 的主体部分 -->  
    </body>  
</html>

引入外置代码源文件的方式在 HTML 中嵌入 JavaScript
对于较长的 JavaScript 源代码,使用内置代码的方式会使得 HTML 代码过长,不符合程序开发模块化的要义。这时可采用引入外部代码文件的方式,即将所有的 JavaScript 代码放在一个扩展名为 .js 的文档中,然后将 script 标签的 src 属性值设置为待引入的 JavaScript 文件的路径名,再将 <script></script> 放在 <head></head> 或者 <body></body> 之间。如下是一个实例:
我们将 JavaScript 代码放在 myjs.js 中,HTML 代码放在 hello.html 中,两者在同一个目录下,其内容分别是:
myjs.js 如下:

console.log("在HTML中嵌入JavaScript,这里是JS部分");

注意:上面的代码中千万不要再加 <script></script> 标签,这些标签是 HTML 语言的内容。
hello.html 如下:

<!DOCTYPE html>  
<html>  
    <head>  
        <script src="myjs.js">  
        </script>  
    </head>  
    <body>  
    <!-- 这里是 HTML 的主体部分 -->  
    </body>  
</html>

注意:这里 src 属性的值 JavaScript 文件的路径名,而不是文件名!这里因为是在同一个目录下,所以路径名同文件名。

# 变量

# JavaScript 中的变量

不同于 C 或 Java,JavaScript 是一种动态类型的语言,即申明的时候不指定变量的数据类型,而在运行的时候根据变量的具体值动态的判断变量的数据类型。
JavaScript 的变量名以字母或者 $ 或者_开头;变量名只能含有字母、数字、下划线和美元符号;大小写敏感;不能使用保留的关键字,如 html、var、function 等,这一条一定要记住,使用关键字造成的错误往往很难排除。

# JavaScript 中的变量的申明、初始化和赋值

  • 变量的申明
    在 JavaScript 中,申明变量以关键字 var 开头,空一格后再接变量的名字;当然,可以一次申明多个变量,这时 var 只需要出现一次,多个变量名之间用英文的逗号隔开即可。如:
var myvar1;     // 申明变量 "myvar1"  
var myvar2,myvar3,myvar4;     // 一次申明三个变量
  • 变量的初始化和赋值
    既然变量是用来记录数据的,如何给变量赋值呢?简单来说,和数学中一样,用一个等号连接变量名和变量的值即可,对于数字的赋值,直接用等号连接数字和变量,对于字符串的赋值,需要将字符串包含在英文双引号之中。
    变量的第一次赋值称之为初始化。
    你可能已经想到了,申明和初始化能一起进行吗?答案是肯定的,下面我们给出具体的例子:
var numberVar;     // 申明  
numberVar = 1;     // 赋值为数字  
var stringVar;     // 申明  
stringVar = "I am a String";     // 赋值为字符串  
var myNumber = 2;     // 申明的同时赋值为数字  
var myString = "我是字符串";     // 申明的同时赋值  
var number1 = 1,number2 = 2;     // 一次申明、赋值多个变量

注意:一个变量经过多次赋值,它的值为最后一次赋值的值。

# JavaScript 中的变量的作用域

变量的作用范围,或者说作用域,是指变量保持有效的范围,JavaScript 中的变量广义上来说分为局部变量和全局变量。

  • 全局变量
    在函数外部申明的变量称为全局变量,全局变量的作用自申明的地方起,到整个 JavaScript 文件的末尾(包括这其中的所有函数的内部)。下面是一个例子:
var wholeVar = 12;     // 申明并初始化一个全局变量  
function() {  
    var localVar = 1;     // 局部变量  
    console.log(wholeVar+localVar); // 输出 13  
}  
console.log(wholeVar);     // 输出 12
  • 局部变量
    局部变量是指申明在函数内部的变量,其作用域仅是本函数内部,在函数外不可用。
    如果局部变量和全局变量的名字相同,那么在函数内部全局变量会被局部变量覆盖。
var myVar = 1;     // 全局变量  
function scope() {  
    var myVar = 2;     // 局部变量,覆盖了上面的值  
    console.log(myVar);     // 输出 2  
}
  • 申明提前
    JavaScript 局部变量有一个很重要的概念,叫申明提前,我们先来看一个例子。
var wholeVar = 1;     // 全局变量  
function myTest() {  
    console.log(wholeVar);  
    var wholeVar = 2;  
    console.log(wholeVar);  
}

关于第三行的输出,你的第一反应一定是 1 吧,正确答案是 undefined。这是因为在函数内部,变量不论在何处申明,都应该看成是在最开始申明(赋值不会看成是在最开始赋值,这就是不输出 2 的原因),这就是 “申明提前”,所以,以上代码等价于:

var wholeVar = 1;  
function myTest() {  
    var wholeVar;     // 申明提前了,覆盖了全局变量  
    console.log(wholeVar);     // 上面只申明,没赋值  
    wholeVar = 2;  
    console.log(wholeVar);  
}

注意:这个地方不太好理解,所以我们在编程的时候局部变量的名字最好不要和全局变量冲突。

# 数据类型

JavaScript 的数据类型有数字、字符串、布尔型、对象类型、数组、null 和 undefined。

# 数据类型介绍

# 数字类型

JavaScript 中的数字类型指整数和浮点数,不刻意区分二者。

JavaScript 还支持 16 进制的整数,在所要表示的 16 进制数前面加上 0x 或者 0X 即可,如 0x1f 表示整数 31。

对于较大或较小的数,JavaScript 还支持科学记数法,如 2e3 表示 2000。

对于一般的数学运算,如加减乘除,和数学上的表达方式相同。对于稍微复杂的运算,需要通过 Math 对象定义的函数来实现,下面是一些例子:

var number1 = 0X11;     //17  
var number2 = 2.01e-2;     //2.01*0.01  
var number3 = Math.sqrt(9);     // 计算 9 的平方根

# 字符串

在 JavaScript 中,没有字符的说法,字符看成长度为 1 的字符串,字符串指包含在单引号或者双引号中的文本。

需要特别注意的是,字符串中的字符不能和外侧的单引号或者双引号构成一个引号对,如果字符串中有引号,需要用转义字符将这些引号变为普通字符,简单来说,转义字符的功能就是使字符串中的字符不被误认为该字符串的结束符号。

如 I'm studying a language,需要用 \ 把中间的单引号转义:

var tran = 'I\'m studying language';

# 布尔型

布尔型:有两种逻辑状态的类型,它的值只有 true 和 false 两个,分别表示正确、错误。

var boolType1 = true;
var boolType2 = false;
常用在控制结构的不同入口的判断上,如:

if (myNumber == 1) { //myNumber 为 1 则返回 true 并进入下面的句子
console.log ("myNumber 值为 1");
}
else {
console.log ("myNumber 值不为 1");
}

# 数组

JavaScript 中的数组是数据的集合,每一个数据在数组中对应一个位置,称为该数据的索引。数据称为数组中的元素,JavaScript 数组中的元素可以是不同的数据类型。

var myArray = [1,2,true,"string",3.2];
上面就定义了一个含有整数、布尔型、字符串、浮点数的数组。

# null 和 undefined

undefined 表示某个变量没有被赋值,比如,变量在申明的时候没有赋值,那么它的值就是 undefined。null 是对象,是一个空的对象引用。

var myVar;  
console.log(myVar);  
console.log(a);

如上面所示,尝试输出变量 myVar,结果会输出 undefined,因为这个变量只申明,没有赋值。而尝试输出变量 a 会产生错误,因为这个变量没有定义,是一个空的对象引用。

# 对象类型

JavaScript 是面向对象的语言,严格的来说,在 JavaScript 中,一切都可称为对象。但是我们这里介绍的对象仅指键值对的集合,可以类比于 C 中的结构体或者 Java 中的对象。

# 对象的创建:

var student = {  
    name:"Peter",  
    age:23,  
    gender:male};     // 申明并初始化对象

# 对象的使用,比如获取对象里的某个属性的值:

console.log(student.name);     // 输出 "Peter"

还可以更改这个属性的值:

student.name = "Bob";  
console.log(student.name);     // 输出 "Bob"

# 数据类型转换

在 JavaScript 中,从前端页面获得的值都是字符串类型,包括数字也会被识别为字符串类型,这自然就产生了转换的需求。

# 字符串转整数

如果你想把一个字符串转换成整数,有两种方式。

使用 parseInt () 方法,参数为字符串,结果为该字符串转换而来的整数;
转化规则是:如果字符串的首字符不是一个数字,转换失败,返回 NaN;否则,转换到字符串中第一个不是数字的字符止,即,遇到字母、小数点下划线等字符立即停止转换。需要注意的是,16 进制的符号 0x 不会让转换停止。
parseInt () 还可以有第二个参数,表示待转换字符串的进制。下面给一些例子:

parseInt("12");  
parseInt("12.2");  
parseInt("C",16);  
parseInt("12a2");  
parseInt("0XC");     // 以上均返回数字 12  
parseInt("a12");     // 失败

# 使用 Number () 进行强制类型转换;

使用 Number () 转换一个字符串,这个字符串必须是只含有数字的字符串,即数字的字符串形式。与上面的 parseInt () 方法对比可知,Number () 实现的是更加严格的字符串转换为数字操作。因为对于 12a3 这种含有字母等非数字字符的字符串,Number () 会报错。下面是一些例子。

Number("12");     // 返回 12  
Number("12a2");   // 返回 NaN  
Number("");       // 返回 0

# 字符串转小数

与整数相同,字符串转小数也有两种方式:parseFloat () 和 Number ()。

parseFloat () 方法只转换到字符串中第一个不是数字的字符为止,当然这个字符不包括第一个小数点。这里有些不好理解,下面用例子解释。

parseFloat("12");      // 返回 12  
parseFloat("12.2a");   // 返回 12.2  
parseFloat("12.2.2");  // 返回 12.2,第二个小数点会让转换停止  
parseFloat(null);      // 返回 0

# 数字转字符串

toString () 实现一般的数字转字符串,String () 则是强制类型转换。

toString () 括号内有一个可选的参数,指以几进制的形式转换该字符串,如数字 12 调用 toString (16) 得到的结果就是 C,即 12 的 16 进制表示方式。

String () 可以转换 null 和 undefined,而 toString () 不可以。

var myNum = 15;  
console.log(myNum.toString());       // 输出 "15"  
console.log(myNum.toString(16));     // 输出 "F"  
console.log(String(myNum));          // 输出 "15"

# 布尔型与其他类型的相互转换

布尔型的值只有两个 true 和 false 。转换规则如下:

布尔型转为字符串直接就是字符串 true 或者 false;
布尔型中的 true 转换为数字 1,布尔型中的 false 转换为数字 0;
数字 0、null、undefined、空字符串转换为布尔型的 false,其他所有都是转换为 true。
下面例子中的 Boolean () 方法实现其他的类型转布尔型。

var myBool = ture;  
myBool.toString();     // 返回 "true"  
Number(true);          // 返回 1  
Boolean("js");         // 返回 true  
Boolean("");           // 返回 false

注意,上面讲的空字符串是 "",而不是空格字符串" ",这两个不同,后者双引号之间有一个英文字符的大小的空位,他们转为布尔型的结果不同:

Boolean("");      // 返回 false  
Boolean(" ");     // 返回 true

# 隐式转换

JavaScript 是一种弱类型语言,不同类型的变量在运算符的作用下会发生类型转换。这个是编译环境下直接进行的,所以叫隐式类型转换。下面是一些转换规则:

  • + 运算的两个操作数是数字和字符串,数字会被转换为字符串;
  • + 运算的两个操作数是数字和布尔型,布尔型会被转换为数字;
  • + 运算的两个操作数是字符串和布尔型,布尔型会被转换为字符串;
  • 减、乘、除、取余运算会把其他类型转换为数字;
  • if 括号中单独的一个变量会被转换为布尔型。

# 运算符

# 对象

# 对象的创建

# 定义

JavaScript 中的一切都是对象,这是该语言的一个很大的特点。像字符串、数组等已经定义的对象叫做内置对象。用户自己也可以定义对象,叫做自定义对象。本实训讲的对象特指自定义对象,自定义对象指数据和函数(又叫方法)的集合。数据指变量名和变量的值构成的组合。如下图所示:

下面介绍五种创建对象的方法,其中通过对象字面量和使用构造函数创建对象最常用。

# 对象字面量

这是最常用的创建对象的方法,通过新建一个键值对的集合(对象字面量)创建对象,如下:

var song = {  
    name:"Liekkas",  
      time:180,  
      "song language":English,  
      singer: {  
        singerName:"Sofia Jannok",  
            singerAge:30  
    }  
};

键值对中的键指的是属性的名字,若其中含有空格,名字需要用双引号包含在内。值指的是属性的值,可以是基本类型:如字符串,数字,布尔型,也可以是一个对象。键值对之间用逗号隔开,最后一个键值对后面没有逗号,所有的键值对在一个大括号中。

# 通过关键字 new 创建对象

通过 new 关键字创建对象也是一个常用的方法。如下:

var Store = new Object();// 创建对象的一个实例  
Store.name = "lofo Market";  
Store.location = "NO.13 Five Avenue";  
Store.salesVolume = 1000000;

# 通过工厂方法创建对象

工厂方法就是通过函数创建对象,函数封装了创建对象的过程。

这是一种通过函数创建对象的方法,函数封装了对象的创建过程,创建新对象时只需要调用该函数即可。这种方法适合于一次创建多个对象。

// 对象的创建函数  
function createStoreObject(name,location,salesVolume) {  
    var store = new Object();  
    store.name = name;  
    store.locaion = location;  
    store.salesVolume = salesVolume;  
    store.display = function() {  
          console.log(this.name);  
    };  
    return store;  
}  
// 利用该函数创建一个对象  
var store1 = createStoreObject("panda express","No.1,People Street",200000);

这样就创建了一个名为 store1 的对象,注意这个对象除了属性之外还有一个方法 display。要创建更多的类似 store1 的对象,直接调用该函数即可。

# 使用构造函数创建对象

上面虽然也是通过函数创建对象,但不是构造函数,只是普通函数。构造函数名必须以大写字母开头,函数体内没有返回语句。

// 构造函数  
function Store(name,location,salesVolume) {  
    this.name = name;  
    this.locaion = location;  
    this.salesVolume = salesVolume;  
}  
// 创建对象的实例  
var myStore = new Store("KeyExp","No.1,L.Street",540000);

上面的代码首先是 Store 对象的构造函数,然后用该构造函数创建了 Store 对象的一个实例 myStore。

# 使用原型 (prototype) 创建对象

当我们创建一个函数时,函数就会自动拥有一个 prototype 属性,这个属性的值是一个对象,这个对象被称为该函数的原型对象。也可以叫做原型。

当用 new 关键字加函数的模式创建一个对象时,这个对象就会有一个默认的不可见的属性 [[Prototype]],该属性的值就是上面提到的原型对象。如下图所示:

JavaScript 中每个对象都有一个属性 [[Prototype]],指向它的原型对象,该原型对象又具有一个自己的 [[Prototype]],层层向上直到一个对象的原型为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。如下图所示:

JavaScript 中每个对象都有一个属性 [[Prototype]],指向它的原型对象,该原型对象又具有一个自己的 [[Prototype]],层层向上直到一个对象的原型为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。如下图所示:

这种方法是对使用构造函数创建对象的改进,使用构造函数创建一个对象时,会把构造函数中的方法(上面的构造函数只有属性的键值对,没有方法)都创建一遍,浪费内存,使用原型不存在这个问题。

function Store() {};  
Store.prototype.name = "SF Express";  
Store.prototype.locaion = "Hong Kong";  
Store.prototype.salesVolume = 1200000000;  
// 创建对象  
var myStore = new Store();  
// 创建一个新的对象  
var hisStore = new Store();  
hisStore.name = "STO Express";// 覆盖了原来的 name 属性

这种方法的好处是,创建一个新的对象时,可以更改部分属性的值。

# 属性的增删改查

在 Java 中,当实体类建立以后,类的属性只能获取与修改,不能增加与删除。但是因为 JavaScript 是动态类型的语言,JavaScript 中对象的属性具有增删改查所有的操作。

# 属性的获取

# 方式一

属性的获取有两种方式,一种是使用。符号,符号左侧是对象的名字,符号右侧是属性的名字,如下:

var student = {name:"Alice",gender:"girl"};  
console.log(student.name);// 输出 Alice

这种情况下属性名必须是静态的字符串,即不能是通过计算或者字符串的拼接形成的字符串。

# 方式二

另外一种是使用 [""] 符号,符号的左边是对象的名字,双引号中间是属性的名字,这种情况下属性名可以是一个表达式,只要表达式的值是一个字符串即可。如下:

var student = {name:"Alice",gender:"girl"};  
console.log(student["name"]);// 输出 Alice

有两种情况必须使用第二种方式:

属性名含有空格字符,如 student ["first name"],这时不能用 student.first name 代替,编译器无法解释后者;

属性名动态生成,比如用 for 循环获取前端连续 id 的值,这种 id 名之间一般有特定关系。如下面的例子:

for(int i = 0;i < 5;i ++) {  
    console.log(student["id"+i]);  
}

# 属性的修改与新增

属性的修改指修改已有属性的值,这个直接用赋值符号即可。

属性的新增与修改在形式上完全相同,区别仅在于编译器会根据属性的名字判断是否有该属性,有则修改,没有则新增。

var student = {  
    name:"Kim",  
    age:21  
};  
student.age = 20;// 修改属性,覆盖了原来的值 21  
student.gender = "female";// 新增属性 gender

# 删除属性

JavaScript 中的属性还可以删除,这在其他的面向对象语言如 Java 或者 C++ 中是无法想象的,删除通过 delete 运算符实现。删除成功返回布尔型 true,删除失败也是返回 true,所以在删除之前需要判断一个属性是否存在,这个内容将在下一关讲解。

需要注意的是,对象只能删除自己特有的属性,而不能删除继承自原型对象的属性。同时,对象在删除属性时,要防止删除被其他对象继承的属性,因为这样会导致程序出错。

var Store = new Object();  
Store.name = "lofo Market";  
Store.location = "NO.13 Five Avenue";  
console.log(delete Store.name);// 删除成功,输出 true  
console.log(Store.name);// 已删除,返回 undefined  
delete Store.prototype;// 删除失败,非自有属性

# 属性的检测和枚举

在 JavaScript 编程实践中,如果我们调用别人的接口,常常需要了解实体是否具有某个属性。

# 属性的检测

属性的检测指检查对象是否有某个属性或者方法,需要使用运算符 in,in 的左侧是属性或者方法名,右侧是检查对象,对象有该属性或者方法则返回 true,否则返回 false,如下:

var school = {  
    name:"SJTU",  
    location:"ShangHai",  
    studentNum:40000,  
    display:function() {  
          console.log(this.name);  
    }  
};  
// 检测属性  
console.log("name" in school);// 输出 true  
console.log("sales" in school);// 输出 false  
// 检测方法  
console.log("display" in school);// 输出 true  
console.log("print" in school);// 输出 false

这里的属性名是字符串,必须用双引号包含在内。

还可以用 hasOwnProperty () 检测对象是否具有某个自有属性或方法。括号内的参数是属性或者方法的名字。

所谓自有属性或者方法,是指对象自己定义的属性或者方法,而不是从原型链上继承来的。

var school = {  
    name:"SJTU",  
    location:"ShangHai",  
    studentNum:40000,  
    display:function() {  
          console.log(this.name);  
    }  
};  
console.log(school.hasOwnProperty("studentNum"));//true  
console.log(school.hasOwnProperty("hasOwnProperty"));//false

因为 hasOwnProperty 方法继承自 object 对象,不是自有方法,所以返回 false。

# 属性的枚举

定义:属性的枚举指按顺序逐个的列出属性的名字。如下面的例子:

var person = {  
    name:"Ye",  
    gender:"Gril",  
    age:23,  
    salary:23000,  
    height:1.78  
}

根据前面的知识,我们知道对象 person 有五个属性,所谓枚举,就是依次列出这五个属性的名字,即:name、gender、age、salary、height,至于它们排列的顺序,在不同的浏览器中的结果不同,这里不讨论。

在继续下面的知识点之前,首先要知道一个概念:可枚举性(enumerable),这是对象的属性的一个性质,用户自己定义的属性默认为可枚举,系统内置的对象的属性默认为不可枚举。

枚举属性有三种方法:

  • for...in... 循环;
    可以枚举所有可枚举的属性,包括继承的属性。如下:
// 首先定义一个 school 对象,它从原型链上继承的属性都是不可枚举的,而下面自定义的四个属性或者方法都是可枚举的  
var school = {  
  name:"SJTU",  
  location:"ShangHai",  
  studentNum:40000,  
  display:function() {  
        console.log(this.name);  
  }  
};  
// 枚举 school 的属性  
// 下面的圆括号中的 att 表示对象的属性,school 表示对象  
for(var att in school) {  
  // 依次输出 name,location,studentNum,display  
  console.log(att);  
}

圆括号里面的表达式中,att 表示对象的属性,school 表示该对象,这个循环将依次遍历对象的所有可枚举属性,每次输出一个属性的值。

  • Object.getOwnPropertyNames();
    括号中有一个参数,是要枚举的对象。该表达式将返回对象的所有自有属性的名字,不区分是否可枚举,结果以字符串数组的形式呈现,如下:
// 定义一个 school 对象  
var school = {  
  name:"SJTU",  
  location:"ShangHai",  
  studentNum:40000,  
  display:function() {  
        console.log(this.name);  
  }  
};  
// 为 school 对象增加一个不可枚举的属性 range  
Object.defineProperty(school, "range", {  
  value: 4,// 设置 range 属性的值  
  enumerable: false// 设置 range 属性为不可枚举  
});  
// 输出 ["name","location","studentNum","display","range"]  
console.log(Object.getOwnPropertyNames(school));

# 文档元素获取

# 通过 id 获取文档元素

# 什么是 DOM

Document Object Module,简称 DOM,中文名文档对象模型。在网页上,组成页面(又叫文档)的一个个对象被组织在树形结构中,用这种结构表示它们之间的层次关系,表示文档中对象的标准模型就称为 DOM。

DOM 的作用是给 HTML 文档提供一个标准的树状模型,这样开发人员就能够通过 DOM 提供的接口去操作 HTML 里面的元素。

# 文档元素

<html>  
    <head>  
        <title>这里是标题</title>  
    </head>  
    <body>  
        <p>这是我学习JavaScript的网址:</p>  
        <a href="https://www.educoder.net/paths">JavaScript学习手册</a>  
    </body>  
</html>

文档元素:指的就是 <html><head> 等等这样一个个的标签和里面的内容。

比如文档元素 <title> 就是这样:

`<title>`这里是标题`</title>  `

在 JavaScript 中,元素 <title> 对应一个对象,这个对象有一个属性的值是 “这里是标题”。

所以,用 JS 操作这些文档元素,操作的就是它们对应的 JS 对象。

# 节点树

从代码的缩进可以知道,文档元素之间有层次关系,如下:

上面的图和数据结构中树的概念类似,被称为节点树。 <html> 是根节点,网页的所有文档元素都在里面, <head><body> 是两个子节点,分别存储网页标题有关内容和网页的主体部分。

JavaScript 要操作这些元素,第一步自然是获得这些元素对应的 JavaScript 对象,那么,怎么获取呢?

# 通过 id 获取文档元素

文档元素一般都有一个 id 属性,它的值在本文档中唯一,如下:

<p id="myId">这是我学习JavaScript的网址:</p>

用这个 id 获取 <p> 元素的方法如下:

var pElement = document.getElementById("myId");

其中 document 表示整个文档,getElementById () 是 document 对象的一个方法,参数是 id 属性的值 myId。

获取的 pElement 就代表了 <p> 标签以及里面的内容,接下来,可以通过 pElement 操作这个元素。比如可以用弹框展示一下 <p> 标签里面的内容:

window.alert(pElement.innerText);
<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>get element by id</title>  
</head>  
<body>  
    <a id="a1" src="https://www.google.com">Google</a>  
    <p id="p1">this is a text</p>  
    <script>  
        <!-- 请在此处编写代码 -->  
        <!---------Begin--------->  
        var myElement = document.getElementById("a1");  
        <!---------End--------->  
        myElement.href="https://www.educoder.net";  
    </script>  
</body>  
</html>

# 通过类名获取文档元素

除了 id 以外,文档元素另外一个常见的属性是类名。

# 通过类名获取文档元素

文档元素的类名不唯一(存在多个文档元素的类名相同的情况),如下:

<p class="myName">段落</p>  
<a class="myName" href="https://www.educoder.net">这是一个链接</a>

document 的 getElementsByClassName()方法用来获取指定类名的文档元素数组(NodeList,一般叫节点列表),如下:

var myNodeList = document.getElementsByClassName("myName");

这样,myNodeList [0] 就是 <p> 元素,而 myNodeList [1] 就是 <a> 元素,通过这个方法的名字我们也可以知道获取的标签不唯一。

我们以弹框的形式查看一下 <p> 里面的内容:

window.alert(myNodeList[0].innerText);

示例

var myElement = document.getElementsByClassName("myName")[3];  
        <!---------End--------->  
        myElement.innerText="I changed the text";

# 通过标签名获取文档元素

# 通过标签的名字获取文档元素

标签名指的是 <> 里面的字符串,document 对象的 getElementsByTagName () 获取整个文档中指定名字的所有标签,显然,结果是一个文档元素数组(节点列表),方法的名字也暗示了这一点。

<div id="div1">  
    <p id="p1">文本1</p>  
    <p id="p2">文本2</p>  
    <a name="a1">链接</a>  
</div>  
<div id="div2">  
    <p id="p3" name="a1">文本3</p>  
</div>

获取所有的 <div> 元素,如下:

var allDiv = document.getElementsByTagName("div");

为了显示效果,我们以页面弹框的形式展示第一个 <div> 里面的内容:

window.alert(allDiv[0]);

# 获取标签内部的子元素

我们获取到的文档元素,也有 getElementsByTagName () 方法,作用是获取该元素内部指定名字的所有子元素。比如,要获取第一个 <div> 里面所有的 <a> 元素,代码如下:

// 变量 allDiv 上面有,这里不再重复!  
var allLink = allDiv[0].getElementsByTagName("a");

这样就获取了第一个 <div> 里面的所有超链接元素。

# 示例

<!DOCTYPE html>  
<html lang="en">  
<head>  
    <meta charset="UTF-8">  
    <title>get element by id</title>
</head>  
<body>  
    <div class="diva">  
        <a href="https://www.educoder.net">EduCoder</a>  
        <a href="https://www.facebook.com">FaceBook</a>  
    </div>  
    <div class="divb">  
        <a href="https://www.twitter.com">Twitter</a>  
        <form name="myForm"></form>  
        <a href="https://www.nudt.edu.cn">NUDT</a>  
    </div>  
    <p id="pp">this is a text</p>  
<script>  
    <!-- 请在此处编写代码 -->  
    <!---------Begin--------->  
     var temp= document.getElementsByTagName("div")[1];  
     var myElement = temp.getElementsByTagName("a")[1];  
    <!---------End--------->  
    myElement.innerText="nudt";  
</script>  
</body>  
</html>

# 属性值的获取

获取文档元素的属性
通过前面的学习,我们可以发现,文档元素后面都会跟着相应的属性,比如 <a> 后面都会有一个 href 属性,用来表示超链接的地址,即点击这个超链接后跳往的目标页的地址。

怎么获取属性值呢?先看一段 html 代码:

<a href="https://www.educoder.net" target="_blank">EduCoder</a>

先获取文档元素:

var aElement = document.getElementsByTagName("a").[0];

然后通过获取到的元素的属性名来得到属性值:

var hrefValue = aElement.href;
console.log(hrefValue);    // 输出 https://www.educoder.net

从上面可以看出, 文档元素.属性名 即获得了该属性的值。

# getAttribute()

getAttribute(a) 用来获取属性值,a 表示属性的名字。比如上面获取超链接的 href 属性值,也可以这样写:

console.log(aElement.getAttribute("href"));    
// 输出 https://www.educoder.net

区别是: getAttribute() 返回的值统一为字符串,而第一种方法会返回属性实际的值,比如 <input>maxLength 属性的值应该是数值,第一种方法就会返回数值, getAttribute() 返回了字符串

<input type="name" maxLength=16 id="inputId"/>
//typeof 检测变量的类型
var result1 = document.getElementById("inputId").maxLength;    // 返回 16
var result2 = document.getElementById("inputId").getAttribute("maxLength");    // 返回 "16"
console.log(typeof(result1));    // 输出 number
console.log(typeof(result2));    //  输出 string

# 特别提醒

class 等文档元素的属性,不能直接用 文档元素对象.class 来获取,因为 class 是 JavaScript 中的关键字,需要用 className 来代替。

但是,如果用的是 getAttribute() ,直接用 class 作为参数就行。

<a class="aClass" id="aId">超链接</a>
document.getElementById("aId").className;// 返回 "aClass"
document.getElementById("aId").getAttribute("class");// 返回 "aClass"

# 示例

1662171251705

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
</head>
<body>
    <p id="p"></p>
    <img class="imgClass"/>
    <a id="a"></a>
    <script>
        <!-- 请在此处编写代码 -->
        <!---------Begin--------->
        var myElement = document.getElementsByClassName("imgClass")[0];
        var srcValue = myElement.className;
        <!---------End--------->
        console.log(srcValue);
    </script>
</body>
</html>