开发者学堂课程【高校精品课-上海交通大学 -互联网应用开发技术:Scripting&JavaScript 1】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/76/detail/15742
Scripting&JavaScript 1
内容介绍:
一、脚本的含义
二、脚本的语法
三、脚本的数组
今天讲述的内容是 Web 前端的脚本机制和 JavaScript。因为在后面做前端的时候都要用 JavaScript编写,包括 React 或者是 Vue 。所以这节课讲述前端的脚本机制。首先,什么是脚本机制?Scripting 用 ing 形式表示其不只是简简单单的写脚本,而是此脚本是要在前端去执行的。下面是 JavaScript 的一些语法。
Scripting
JavaScript
- Syntax overview
- HTML DOM Objects
- ECMAScript & JavaScript
- JavaScript Compatibility Techniques
- JavaScript Closure Compiler
包括它是如何操作 HTML 里面的对象,因为写前端本质上就是要将页面的内容呈现给客户端。实际上操作的对象大多数都是 HTML 里面的,比如说对 DIV 里面的内容进行操作、在里面增加一些内容或者是动态的改写一些内容。然后看 JavaScript 的一个有关它的兼容性问题(Compatibility Techniques),还有它的闭包编译器(Closure Compiler)是指的什么?
然后简单介绍一些常用的框架:
Rich Client JS Framework
- Angular
- React
- jQuery
- Bootstrap
同时还会讲到 Vue,这也是很重要的框架。
一、脚本的含义
脚本是在浏览器里面运行的,但是脚本和 C++程序或者其他的编译型程序不同的地方在于它不需要编译,直接在浏览器里面解释执行。那么在实际编写和调试的时候,可能会碰到的两个问题。
第一个问题:它会完全按照你写的去执行,也就是缺乏编译的过程。在之后学习编译的时候,我们会知道编译实际上是要对程序做一些优化的。那么举一个例子,比如说你写了一个 for 循环(for(int i = .......))这个循环结束之后,你可能又写了一个for循环(for(int j = ......))。这里我们指的不是两个重循环在嵌套,而是两个无关的循环。那么在编译的时候,编译器就会做一些优化,比如说它会复用同一块内存空间去存 i 和 j 。
因为他们的生存周期是没有重叠的,所以他们可以复用这一块儿内存,这就是其中之一的优化,还有很多其他的优化。但是一个程序如果是解释执行的。那么它缺少这个过程,所以一方面说解释执行的程序执行的比较慢,是因为编译执行程序的话,都把它编译成了机器上的机器码,或者是像 JavaScript 的中间码,像 java 的字节码,但是无论是字节码还是机器码,它的执行都比解释执行要快。
另一方面,因为缺少边缘过程。就是像编译器在这里做优化的动作。所以导致程序执行起来效率不是最高。所以第一方面就是在执行程序的时候,相对来说它没有其他编译型语言编写的程序那么高效。
第二个问题:脚本基本上都是在浏览器(browser)里执行的,那么它就会有一个很严重的问题,也就是安全问题。关于安全问题,这里有一个沙箱机制(sandbox),它会限制 JavaScript 的一些动作,也就是有一些操作是不能执行的,也就是说其安全权限没有本地的程序大。所以可能会遇到能执行的动作是有限这种情况。也就是说脚本程序,尤其像 JavaScript 这种在浏览器里执行的脚本程序,它主要的两个问题就是慢跟可能比较受限。当然还有其他的一些细节,比如说后面谈到的 JavaScript 的兼容性问题。
如果有同学已经写过这方面的程序,就会发现 JavaScript 的程序比较难调试。原因就是其相对于 java ,它有一些方面放的比较宽,比如说它是弱类型,而没有要求是强类型。宽就意味着比较容易出错,而且出错的时候比较难以调试。
当然脚本不止 JavaScript 一种,还有用 Action Script 写的像 flex 的,也就是平常看到的 flash 的操作,这种程序也是可以的。也就是说不管是哪一种脚本,它都是为了让网页变得更加动态,动态就是说你在浏览器这一端做一些动态操作的时候,不用每一次对页面内容进更新。更新就是它需要到服务器端去发一个请求,让服务器端去生成一个改变内容的页面反馈客户端。
这是第一节课讲的,就是把一部分的计算的工作推到了客户端,在客户端的浏览器里面执行,这个执行靠的就是脚本。所以脚本机制的一个初衷就是让页面变得更加的动态。经常看到的脚本机制,比如说后面会谈到的 AJAX(Asynchronous JavaScript and XML)异步的去执行这个调用。异步到后面在进行讲解。现在只有知道的脚本机制是在浏览器执行的。
而常用的就是 JavaScript ,无论哪一个框架都是首选。语言上基本的语法的一些规定,由下图列出,这些东西来自于下方的网站。
二、脚本的语法
下面是节选的一些基本语法。
Strings
- Strings are values made up of text and can contain letters, numbers,symbols, punctuation, and even emoji.
- Strings are contained within a pair of either single quotation marks ‘’or double quotation marks " ".
- Enclosing quotation marks
"It's six o'clock. ";
‘Remember to say "please" and "thank you." ';
'It\ 's six o\'clock. ';
"Remember to say \"please \" and \" thank you. \"";
首先 JavaScript 里面都是字符串,很多操作也是字符串。因为我们之前说过,在客户端(browser)和浏览器之间在进行交互的时候,传递的内容都是纯文本,哪怕传递的内容是数字。所以本质上来说它就是字符串,所以字符串操作是个非常基础的一个操作,在 JavaScript 里面。字符串可以用单引号或者双引号引起来,而且字符串可以包含表情。
例如:
如果字符串里面带引号,这种情况要进行转义。
比如:
"It's six o'clock. ";
‘Remember to say "please" and "thank you." ';
'It\ 's six o\'clock. ';
"Remember to say \"please \" and \" thank you. \"";
字符串的一些属性和方法。
字符串的长度:
- EXAMPLE
"caterpillar". length;
- OUTPUT
11
转小写的方法:
- toLowerCase
EXAMPLE
"THE KIDS".toLowerCase();.
OUTPUT
"the kids"
转大写的方法:
EXAMPLE
"工 wish I were big.".toUpperCase();
OUTPUT
"I WISH I WERE BIG."
剔除空格的方法:
- trim
EXAMPLE
" but keep the middle spaces ".trim();
OUTPUT
"but keep the middle spaces"
这里多建议大家对字符串操作的时候尽量都要去调用一下剔除空格制的操作。无论后台用 Java 还是前台用 JavaScript,这个操作都应该做一下,因为有很多空格是看不到的。
比如说在数据库表里面、mysql 里面字段写进去的内容。这个内容后面或者前面是否有前导或者后缀空格。在客户端里可能是看不到的,但是它可能会带有空格。一旦带的话,如果去做字串的比较操作,就会得出一个不相等的结论。
所以要把后缀和前缀的像空格、tab 键、回车这样的空白字符全部给去掉,当然这个操作不会把中间的剔除掉。
数字:进行数字操作的时候,直接写就可以。这里要注意的是,首先在写的时候,如果拿 JavaScript 里面进行前后端的传递的话,看到的数字可能只是字符串,要把它转成数字来处理。如果前端的浏览器里面直接写了一个变量,比如说 :A = 10 + 3.14159,那它确实是数字。但它和其他的语言一样在进行数字操作的时候,都有内部的隐藏的转型。比如说10在计算机里表示的时候,实际上是一个整数,如果是八位也就是十六进制表示的话,10就是0A。但是3.14159在内存里面表示用的是 IEEE-754 这个标准来描述的。那它有符号位,有接码,有尾码,这样的方式表示的,这两个是不能直接相加的,但是他在相加之前会把两个数都转型成同一种,这是背后发生的事情。之前讲过,浮点数是如何表示的,实际上一个整数是做了一次隐性转型的,然后就都按浮点数据进行操作了。
因为 JavaScript 是比较简单的语言,希望大家比较容易上手,所以这种操作它自动就会执行掉,但是它可能会有一个问题,就是它可能不准确,但是这个不准确实际上非常细微。
布尔类型类型:布尔类型比较简单,就是 True 和 False 两个值。
-EXAMPLE
var kitchenLights = false;
kitchenLights = true;
kitchenLights;
- OUTPUT
True
然后有一些基本的加减乘除的操作符。还有群组、连接......这里连接指的是字符串的连接,它会和加号操作符在我们写代码时候产生操作符的重载,重载之后它就会有两个含义,他会根据两边的操作数的不同,自动去理解这个操作府应该是使用的重载的哪一种含义,到底是字块儿连接,还是做加法的操作。然后就是是复制操作符,这些和 C++ 很像,这里就不多说明。
- Arithmetic
- The + operator adds two numbers.
. The - operator subtracts one number from another..
.The * operator multiplies two numbers.
. The / operator divides one number by another.
- Grouping
- ()operator groups other values and operations.
- Concatenation
. The + operator can also concatenate strings, which is another way of saying
it can add them together.
- Assignment
. The = operator assigns values. It's used for setting the value of variables.
定义变量:需要用到 var关键字。例: var X = 100。关于变量名也有一些约束。
Variables
-Naming variables
.Start them with a letter, underscore _,or dollar sign $.
.After the first letter, you can use numbers, as well as letters, underscores, or dollar signs.
.Don't use any of JavaScript's reserved keywords.
-some valid variable names:
var camelCase = "lowercase word,then uppercase" ;
var dinner2Go = "pizza";
var I_AM_HUNGRY = true;
var _He11o_= "what a nice greeting”
var $_$ = "money eyes";
-some invalid variable names :
var total% = 78;
var 2fast2catch = "bold claim";
var function = false;
var class = "easy";
- Variable names are case-sensitive, so myVar, MyVar, and myvar are all different variables.
这里要谈一个问题,就是在定义变量时候还有一个关键词叫 let。在后面写 javascript 程序的时候,凡是写到 var 这种声明的时候。它可能都会建议你改成let。那么 let 是什么意思呢?Let 也是定义一个变量,但是 let 和 var 定义是有差别的。Var 定义变量的作用域要么是函数级,要么是在整个程序的生命周期里面。所以你先定一个 var X = 10。这个 X 是一直存在于这一段脚本执行的过程当中。那如果在底下使用大括号定义 blog。
也就是定义了一个语句块。(语句块儿有哪一些呢?一个 for 循环是一个语句块,一个 while 循环也是一个语句块。)现在我们直接用大括号自己定义一个语句块。在里面又定义了一个 var X = 2。这时候 JavaScript 会认为这个 X = 2,是对前面的 X=10的一个覆盖。在底下需要在执行这个脚本之后。把 demo 的 paragraph 内容给它替换成X值。这时候得到的就是2。也就是说他会认为这里的 X 把外面的 X 的值覆盖了。相当于重新的定义了一次,而且你以后看到的 X,都是在这块里面看到的。这个可能和预期并不符。预期是定义了一个全局变量 X。在这个块里面再定义一个变量 X 等于2,但是这个 X 只在这一个语句块儿里面有效,出了这个语句块就无效了。也就是说在这个语句块里面直接访问 X 它确实等于2,但是出了这个语句块后这个 X 的生命周期结束,这时候去调用 X 就只能访问出了语句块之后存活着的唯一的 X,输出就会是10。
所以 Let 实际就是让你具备一个在一个 block 里面去定义变量的能力。那这个变量只存活在这个 block 之中。在这个block的内部调用 X 的时候,它访问的就是这个 X,在外面的时候就不是了。就像在学习 C++的时候,提到的一个名字,无论是变量名还是函数名。
当在解析一个名字的时候,它解析的过程是先在它最近的块里,然后再到它所属的函数里,如果没有函数的话,就再往外扩一直到整个全局变量,直到找到 X 为止。但是在这个群岛的途径当中,只要在任何一个地方找到了 X,这个变量就认为引用的就是其,然后终止继续往下找一个过程。
这也叫的名字遮蔽或者名字隐藏,它的含义不是这里要讲的内容,所以这里 let 是定义了一个语句块级别的一个变量,它只在这一个语句块儿里面去存活,超过这个定义它的语句块的范围,它就被销毁。
那么为什么在开发工具里面写 JavaScript 时,凡是写 var 的地方,都会画波浪线,这就是在建议你写成 let,原因就是因为它的生命周期是比较受限的,在不用的时候其生命也会结束,也就是说在它的定义域之外,生命就会结束。所以应该尽量节省内存开销,就是尽量都用 let 除非必须用到别的关键词。这就是在编写 JavaScript 程序脚本的时候会到用波浪线建议改成 let 的原因。
这个 let 也可以定义变量,其生命周期比 var 更小,只在其定义的语句块级别的作用域中有意义,所以在例子中将 var 改为了 let。
完整代码如下:
<!DOCTYPE html>
<html>
<body>
<h1>使用var声明变量</h1>
<p id="demo"></p>
<script>
var x = 10;
//Here x is 10{
var x = 2;
//Here x is 2}
//Here x is 2
document.getElementById( "demo" ).innerHTML = x;
</ script>
</ body>
</ html>
函数:函数与 C++中看到的差不多。就是有函数名、参数列表,然后派一个返回值。但是它写法上有点差异,就是不像 C++,例如是public int,表示要返回 int 位置。这里面没有编写,因为在这里,其会根据类型,再写retain时关注的类型,推广其应该返回的什么值。那函数定义前比较简单,和 C++差不多,定义好后就可以去使用它。这里定义了把两个变量相加,然后返回和结果的函数。
Function addTwoNumbers(x,y){
Return x + y;
}
那么函数定义好之后就可以去调用了那比如说这里定义了一个函数,在底下就可以去调用了。
Function greettheplanet(){
Return “hello world!”;
}
Function greettheplanet()
如果带参数,但要用带参数的方式去调用。
Function square(number){
Return number * number;
}
Square(16);
然后增加了一个地方,就是在 ECMAScript6(ES6)这个版本开始支持Lambda 表达式。
也就是说在定义函数时候有两种定义的方法,比如说需要定义函数,其返回两个数字的乘积。上面那种就是在比较旧的 javascript 的版本,也就是在符合 ECMAScript5 的标准基础上实现这种 javascript。这么写跟前面定的函数的定语方法是一样的。
//ES5
Var x = function(x,y){
Return x * y;
}
那么这句语句的意思是说要把 X 和 Y 参数传递了参数的乘积,要给它计算出来以后负X这个函数本身是在做乘法,不然就像上面这里看到的。
Var x = function (a,b){return a * b};
Var z = x(4,3);
那可以把函数定义出来之后,赋值给变量 X,而且 X 就意味是这个函数的代名词,所以在调用 X(4,3)的时候,它实际上就是在执行4*3。这些语法看起来都和自变量没有什么太大差异,但是到 ES6这个版本时,推出了 lambda 表达式,实际上跟 C++的 lambda 表达式很相近,其意思是这样的,现在需要定义一个函数,函数是 lambda 表达式,lambda 表达式用的是箭头(=>),所谓箭头实际上就是一个等号,加上一个大于号。
//ES6
Const x = (x,y) => x * y
这时键盘直接输入不出来的,没有输入可以直接输入箭头,是两个符号。其意思是,定义函数时有这样一种看起来比较简便的方法。前面括号中的(x,y)就是参数列表,那如果这个函数没有参数列表呢?那就用空括号就可以,后面就是这个函数的返回值,那由于这个函数没有复杂的逻辑操作,只是需要返回计算的结果,这就是叫它表达式的原因,后面这是它的计算、返回的结果。那所以其逻辑也就是它要返回参数 X、Y 的乘积。看起来和上面一样,那为什么要用箭头函数呢?大家如果已经看过给大家写的 React 的例子,里面在定义 Excel 类的时候,有很多成员函数,成员函数里全部写的是这种方式,用这种方式定义成员函数。
那为什么要这样做呢?可以看一下其中的差别,先看刚才这种比较常规的函数定义。
Var obj = {
birth:1990,
getAge: function(){
var b = this.birth; // 1990
var fn = function () {
return new Date(). getFullYear() - this . birth;
//this 指向 window 或 undefined, 而不是 obj
};
return fn();
}
};
定义了叫做 obj 的对象,这个对象有属性,birth 表示其是哪一年出生,getage 是它的成员函数,那么在成员函数里,定义变量 B,就是 this birth,这是它的成员函数,所以它可以直接调用,就是this.birth现在指的就是1990。
然后这个函数又定义了一个变量,这个变量本身是另外的函数,这个函数是说当前的时间里面的年份,减去 this.birth,那么它应该返回30,因为今年是2020年。如果这个年份是1990的情况,那么按道理 this.birth 应该就是按年份减去1990,然后得到30。但问题是 this 代指的身份是谁?这个 this 不直接是这个 Get 的函数,而是在这里又定义了一个函数,现在的 this 比较迷茫,在这种常规函数的写法里面,它指向的是当前整个的窗体的对象,或者指向了 undefined 的对象。反正不管怎样,其指的都不是 obj。这在给你带来困扰,就不是当前定义的这个类、对象。那需要 this 指的就是 obj 该怎么写呢?
前面不变,如下方代码所示:
Var obj = {
birth:1990,
getAge: function(){
var b = this.birth; // 1990
然后定义的 fn,刚刚看到这是普通函数,现在用 lambda 表达式来表示。刚才函数没有任何参数,所以底下在写的时候,括号就是刚才说这是没有任何内容的东西,然后后面是它返回的值,返回的前一半,还是当前的时间。它对应的年份没变,后面还是 this.birth。
但是看起来整个完整的这一句话,和前面这一句是没有任何差异的。问题是在一个 lambda 的表达式里,所以现在 this 指向的就是 obj。所以能够正常执行,如果其执行调在对象上调用方法的话,就会返回当前的日期。
那这是写的例子,创建了一个页面,页面里面嵌入这段脚本,脚本里面定义的 obj,在定义变量时,尽量不用 let。所以刚才内容是在底下这链接找到的。
这个链接的内容比较多,但是核心在上方代码中。其他一些细节下来还可以再看,内容是比较多的。
这里将其进行改写,都是 let。那代码跟刚才 ppt 里看到的是类似的。这里是定义了一个 obj 的1990,然后 function。
先来看用常规的函数写,这里需要返回当前预期的年份,减去 this.birth。那在底下页面里面做了一个按钮,这个按钮在鼠标点下后,会调用刚才的函数(show_coords),函数会使用 alert 的方式返回,去显示这个 obj.getAge 对象方法的返回值。那所以在页面看一下,这里点击后,会返回出现 nan,这说明什么呢?
首先 nan 的含义是not a number,就是它不是数字,那也就是说,其没有返回这里需要的那一个结果30。这个说明没有得到数字。
其次从 nan 来看,它应该是返回了一个对象,但并不清楚对象是谁?也就是说,其实这里的 this 到底指向了谁,现在也看不出来。那从这个地方可以看到它是存在问题的,那把它更改一下,把这一段注释掉。
用刚才的 lambda 表达式把它显示出来,然后这里代码没有修改的情况,这里会建议用 let 替换掉 var。把其换成 let 这里就没有提示需要更改的下划线了,当然使用 var 没有问题,系统只是建议。然后把页面内容改成用 lambda 表达式来做,那刚才解释的一样,还是年份减去 this.birth,但是现在已经有指代了。所以再来看一下页面,这里能显示出30,这两个差异其实就在这里。所以下来写东西时,这里为什么会说尽量要用 lambda 表达式来吸引成员、函数呢?
这里看一下之前写的例子,里面基本上用的都是它,原因是因为操作之后的值会修改,就是刚刚说过在给的例子里面是定义了一个 excel类,它的对象就是要去实际化对象,去画了这个页面上,然后每次在上面点击按钮,或者在文本框里输入东西,实际上都会去刷新状态。那也就是说在这个类里写的那些成员函数,实际上都希望沿用的是这个 obj,也就是出现类似时候,希望用都是这个 obj。是这个 obj的 state 做的刷新。所以在写那个例子,里面所有的函数用的都是 lambda 表达式写的方法,没有使用前面的方式。
这里要强调的就是这个 lambda 表达式是将来要去尽量用这种方式来写前端,就是如果碰到一些稀奇古怪的东西,你感觉你搞不定,可能是因为这个原因。
所以要用这个函数来写这种方式来写。另外刚才写的时候有一些细节。就是原来给放的时候没有放这个页面,只放了三个页面,如果你只有三个页面,把它打开点击浏览器,你可能看不到。实际上这里新创建了一个空的 web(web服务器),就是 web 应用,就是那天看到的创建了新的 project,用了 mavem 的模板,创建了一个空的web pp的应用,创建好以后,只写了几个静态页面。如果以这种方式去创建工程化。放这个静态页面内容,点击浏览器就能够在浏览器里看到 suffer,在 suffer 中就能看到。
如果不是以这种方式打开,举个例子就是往 web storm 打开的,直接做了一个空项目,直接就放了三个页面,这时候需要看的话,它可能会报错。
注意这里可以看到它是默认,应该有一个应用服务器跑起来,在8080端口。但是如果按照空的web app 去创建,注意看页面的时候,这个端口是不一样的,其端口在63342。也就是说在 int 或者 web storm 里默认呢,开了 web app 的工程,在里面放进去页面,当需要看的时候,会默认起内嵌的服务器。在63342这个端口,把这个页面露出来,这时候才可以正常的执行、显示这个页面,然后再操作它,才可以得到想要的结果,这是要注意的一个细节!
所以要强调的就是在未来在写的时候,如果碰到了有搞定的问题,发现这个类似的指代或者说其总是在报 This state 找不到对象,那就要明白,实际上是因为可能按前面的方式,在写 this 指代的不是当前正在操作的这个对象,而是指代的是指向的整个 window 或者不知道指代的对象是谁,所以找不到对象,也就是这个想要访问的东西,这是有关函数的东西,然后其他的就比较简单,像控制变量、控制流程。
有条件判断 if、else嵌套,再写这个控制语句,也可以使用switch,switch的写法就跟大家看到 c++的形式很像,不要忘了最后还有 break。
实际也就是说程序里面这些 case 是标号,然后这些语句是一行一行按照顺序写下来的,它只不过在每一行以及前面加了标号,所以从哪儿进去,就从这开始顺序执行下去,一定要记住最后添加 break。这和 C++是一样的,那循环有 for 循环,这种 for 循环是明确知道要循环多少次的。
这种写法比较死,需要先定变量,这个循环变量,在边形语言里面会优化,就指的是这个地方。这种 for 循环是要预先要知道需要循环的次数,或者人为的去把其变成变量,再要去控制它。有更简单的方法,尤其对集合类进行便利的时候,看到其他语言也有的,比如说 java,也就是用 for each循环,就表示对后面集合类里的每个元素按顺序去建立,这是一种 for each 循环,这种循环可能对集合类,操作起来显得更方便一些。这也是大家现在使用的可能比较多的方式。
还有 while 和 do-while 这和 C++都是类似的。所以看到 jsc 这个语言本身可能比较简单,大部分语法如果大家接触 C++的情况下,理解起来都没有什么问题。那其实刚才的箭头函数要知道它,实际上这在其他语言里也有这个特性,无论是 C++还是 java,也就是所谓的Lambda 表达式,其输写会更简单,而且关键是 jscript 有一个特质的地方,就是有关类似的处理会有点差异。其他的例如返回值是一个表达式,并且没有复杂操作这样的函数,它的写法没什么差异。
那函数题里面看到没有任何差异。这是有关 jsc 这个语言本身看到的一些东西。
三、脚本的数组
基本的语法讲完后,就会判断它还有处理数组,数组虽然看见内容比较多,后面还有几节都在讲这个部分,但实际上是没什么难点,这里用中括号处理的,大家看到 C++中括号里的数组,如果大家写过 python 语言的情况下,python 也是用中括号尔表示一个例子,本质上就是数组。
但是它的数组和其他 C++的数组有点不一样,就是 Javascript 是弱类型的,所以它有一些特性,是强类型的语言不具备的。强类型也就是任何变量在编译时刻,就必须要知道它的类型。那弱类型的可以在执行的时刻去推导,而且对类型的约束并不差。那所以看到这个弱类型的数组,在 C++里面可能就发现很难成立。因为它的成员有一个是数值型,一个字符串型,一个是 weak typed 类型,还有布尔类型,它的成员类型可以不一样。
然后数组上当然会有一些属性和方法,就包括看到的长度,它的属性那么连接就是它的方法,把两个数组连接起来,然后对数组还有 pop、push 去增加数组的元素数量或者把里面的某一个元素给弹出来,那 pluto 的话就把对尾的东西往外 Push,后面的 reverse 比较方便的地方就是把数组里所有的元素倒序排列,然后产生突出,它的结果本身又是数组,可以把它复制给另外数组。
所以这是数组的一些操作,再往后就是后面比如说要写 variables的东西,会经常看到需要写类,然后用类里面去实际化出对象。那对象当然可以有一些成员,其成员包括数据成员,例如这里的 name、start、end。也可以像刚才看到的 obj,还可以有函数成员。也就是说跟一般的类定义一样,就是要有属性有动作。所以类就是一个它的属性和动作行为的封装,可以去定义这样的类,然后定义对象。
那当然,如果这个对象只是值对象的话,可以直接这样用大括号来定义比较方便。定义好了之后就可以去检索里面的内容。
在检索里面内容的方式,是直接通过“.+操作”这个可能更符合大家的操作习惯。然后在用 javascript 的时候,实际上刚才看到的都是比较简单的,它的语法在很大程度上在前端,是为了去操作页面,在页面里这些元素,比如说 div,一开始定义的时候,里面可能是空的,那希望通过脚本的执行,在里面填充进东西。
那就类似于刚才希望把内容给它填掉,那如果是这样需求的话,就意味着,要能操作到这样的这些对象,也就是页面连接内容。上次说因为它是这种嵌套式的结构层次型的结构,所以看起来像一棵 tree。所以就表示在操作页面上有很大程度,就像操作由这些标签构成这样的 tree。那所谓的 DOM就是 document,也就是对象模型树。document 这个对象是在页面里,表示了整个这棵树的根,所以得到它就可以在里面建立所有的元素。
比如说在 document上,如果是 document.head,返回的就是页面的head 这样的标签。那就可以操作,像刚才看到的一个例子,就是把p标签里面的内容给替换掉。
那么其在获取时是这样:
按照 Id 来搜索整个页面里的 elementbyid,这里的 id = demo,所以这里用 demo 来搜索就得到了。所以前面的操作,就是在获取这个标签。它实际上返回是整个这一块内容。从开始到结束全给你,全给你之后得到了这一块后,它有一个属性叫 inner,那描述的就是中间加入的这个文本。那现在要把文本替换成 X。它的意思就是执行到这里之后,让这中间地方选为 X,这是通过 document 这个对象来进行操作的。
其可以是 document.head 用来得到 head 的标签;也可以是用document.title 得到 title 这个标签;然后用 body 得到 body 这个标签;或者说用 get Element byid,用 id 的方式来获取某一个元素;当然也可以按照名字 name来获取,也就是说如果需要获取这个页面里面某一种标签,比如说 h1。
大家在讲数据库或者是其他的文件那个 csp 里面,所谓id就是标识图教的唯一做的标识。
所以他们之间存在差异,因为 ID 是唯一的,所以在 ID 的时候返回的是单个的 node。name 刚才说的不太准确,应该不是h1需要,应该是说在标签里面,如果给它起一个属性 name,然后其会按这个去去返回。
只要不是 id,就包括在数据库里操作的时候,如果不是按主键去查找,所有其他的查找方法都应该是返回一个集合,因为只有逐渐能表示唯一的标识的对象,其他的则不能表示唯一标识的对象。所以只要按其他的标准进行查找,返回都是一个集合,需要 byld 整个集合,然后找到想要的那一个元素。
尽管有可能在这个页面里,它的返回应该只有一个 node,那它也是只有一个 node 的集合。这技术其中的差异。