JAVA的起源故事
网景公司
有自己研发的内核
功能:
可以来增强用户和HTML页面的交互过程,可以来控制html元素,让页面有一些动态的效果,增强用户的体验
JavaScript = ECMAScript + JavaScript 自己特有的东西(BOM+DOM)
JavaScript web 开发人员必须学习的 3 门语言中的一门: 1、HTML 定义了网页的内容 2、CSS 描述了网页的布局 3、JavaScript 对网页行为进行编程
ECMAScript :客户端脚本语言的标准
与html结合方式:
(1)内部JS:定义
(2)外部JS:定义
注意:1、
2、
<script> document.getElementById("demo").innerHTML = "我的第一段 JavaScript"; </script>
**注释:**旧的 JavaScript 例子也许会使用 type 属性:
**注释:**type 属性不是必需的。JavaScript 是 HTML 中的默认脚本语言。
JavaScript 能够以不同方式“显示”数据:
使用 window.alert() 写入警告框 使用 document.write() 写入 HTML 输出 使用 innerHTML 写入 HTML 元素 使用 console.log() 写入浏览器控制台
如需访问 HTML 元素,JavaScript 可使用 document.getElementById(id) 方法。
id 属性定义 HTML 元素。innerHTML 属性定义 HTML 内容:
<!DOCTYPE html> <html> <body> <h1>我的第一张网页</h1> <p>我的第一个段落</p> <p id="demo"></p> <script> document.getElementById("demo").innerHTML = 5 + 6; </script> </body> </html>
出于测试目的,使用 document.write() 比较方便:
<!DOCTYPE html> <html> <body> <h1>我的第一张网页</h1> <p>我的第一个段落</p> <script> document.write(5 + 6); </script> </body> </html>
在 HTML 文档完全加载后使用 document.write() 将删除所有已有的 HTML :
<!DOCTYPE html> <html> <body> <h1>我的第一张网页</h1> <p>我的第一个段落</p> <button onclick="document.write(5 + 6)">试一试</button> </body> </html>
document.write() 方法仅用于测试。
您能够使用警告框来显示数据:
<!DOCTYPE html> <html> <body> <h1>我的第一张网页</h1> <p>我的第一个段落</p> <script> window.alert(5 + 6); </script> </body> </html>
在浏览器中,您可使用 console.log() 方法来显示数据。
请通过 F12 来激活浏览器控制台,并在菜单中选择“控制台”
<!DOCTYPE html> <html> <body> <h1>我的第一张网页</h1> <p>我的第一个段落</p> <script> console.log(5 + 6); </script> </body> </html>
原始数据类型(基本数据类型)
1️⃣:number :数字。整数/小数/NaN(not a number 一个不是数字的数字)
2️⃣:string :字符串。“abc” “a”
3️⃣:boolean:true 和 false
4️⃣:null :一个对象为空的占位符
5️⃣:undefined:未定义。如果一个变量没有给初始化值,则会被默认赋值为undefined
JavaScript不区分整数和浮点数,统一用Number表示,以下都是合法的Number类型:
123; // 整数123 0.456; // 浮点数0.456 1.2345e3; // 科学计数法表示1.2345x1000,等同于1234.5 -99; // 负数 NaN; // NaN表示Not a Number,当无法计算结果时用NaN表示 Infinity; // Infinity表示无限大,当数值超过了JavaScript的Number所能表示的最大值时,就表示为Infinity
字符串是以==单引号’或双引号"==括起来的任意文本,比如'abc'
,"xyz"
等等。请注意,''
或""
本身只是一种表示方式,不是字符串的一部分,因此,字符串'abc'
只有a
,b
,c
这3个字符。
JavaScript的字符串就是用''
或""
括起来的字符表示。
如果'
本身也是一个字符,那就可以用""
括起来,比如"I'm OK"
包含的字符是I
,'
,m
,空格,O
,K
这6个字符。
如果字符串内部既包含'
又包含"
怎么办?可以用转义字符\
来标识,比如:
'I\'m \"OK\"!';
表示的字符串内容是:I'm "OK"!
转义字符\
可以转义很多字符,比如\n
表示换行,\t
表示制表符,字符\
本身也要转义,所以\\
表示的字符就是\
。
ASCII字符可以以\x##
形式的十六进制表示,例如:
'\x41'; // 完全等同于 'A'
还可以用\u####
表示一个Unicode字符:
'\u4e2d\u6587'; // 完全等同于 '中文'
由于多行字符串用\n
写起来比较费事,所以最新的ES6标准新增了一种多行字符串的表示方法,用反引号 \* ... \*
表示:
`这是一个 多行 字符串`;
┌─────┐ ┌─────┬─────┬─────┬─────┐ │ ESC │ │ F1 │ F2 │ F3 │ F4 │ │ │ │ │ │ │ │ └─────┘ └─────┴─────┴─────┴─────┘ ┌─────┬─────┬─────┬─────┬─────┐ │ ~ │ ! │ @ │ # │ $ │ │ ` │ 1 │ 2 │ 3 │ 4 │ ├─────┴──┬──┴──┬──┴──┬──┴──┬──┘ │ │ │ │ │ │ tab │ Q │ W │ E │ ├────────┴──┬──┴──┬──┴──┬──┘ │ │ │ │ │ caps lock │ A │ S │ └───────────┴─────┴─────┘
要把多个字符串连接起来,可以用+
号连接:
var name = '小明'; var age = 20; var message = '你好, ' + name + ', 你今年' + age + '岁了!'; alert(message);
字符串常见的操作如下:
var s = 'Hello, world!'; s.length; // 13
要获取字符串某个指定位置的字符,使用类似Array的下标操作,索引号从0开始:
var s = 'Hello, world!'; s[0]; // 'H' s[6]; // ' ' s[7]; // 'w' s[12]; // '!' s[13]; // undefined 超出范围的索引不会报错,但一律返回undefined
需要特别注意的是,字符串是不可变的,如果对字符串的某个索引赋值,不会有任何错误,但是,也没有任何效果:
var s = 'Test'; s[0] = 'X'; alert(s); // s仍然为'Test'
JavaScript为字符串提供了一些常用方法,注意,调用这些方法本身不会改变原有字符串的内容,而是返回一个新字符串
toUpperCase()
把一个字符串全部变为大写:
var s = 'Hello'; s.toUpperCase(); // 返回'HELLO'
toLowerCase()
把一个字符串全部变为小写:
var s = 'Hello'; var lower = s.toLowerCase(); // 返回'hello'并赋值给变量lower lower; // 'hello'
indexOf()
会搜索指定字符串出现的位置:
var s = 'hello, world'; s.indexOf('world'); // 返回7 s.indexOf('World'); // 没有找到指定的子串,返回-1
substring()
返回指定索引区间的子串:
var s = 'hello, world' s.substring(0, 5); // 从索引0开始到5(不包括5),返回'hello' s.substring(7); // 从索引7开始到结束,返回'world'
布尔值和布尔代数的表示完全一致,一个布尔值只有true
、false
两种值,要么是true
,要么是false
,可以直接用true
、false
表示布尔值,也可以通过布尔运算计算出来:
true; // 这是一个true值 false; // 这是一个false值 2 > 1; // 这是一个true值 2 >= 3; // 这是一个false值
&&
运算是 与运算,只有所有都为true
,&&
运算结果才是true
:
true && true; // 这个&&语句计算结果为true true && false; // 这个&&语句计算结果为false false && true && false; // 这个&&语句计算结果为false
||
运算是 或运算,只要其中有一个为true
,||
运算结果就是true
:
false || false; // 这个||语句计算结果为false true || false; // 这个||语句计算结果为true false || true || false; // 这个||语句计算结果为true
!
运算是 非运算,它是一个单目运算符,把true
变成false
,false
变成true
:
! true; // 结果为false ! false; // 结果为true ! (2 > 5); // 结果为true
布尔值经常用在条件判断中,比如:
var age = 15; if (age >= 18) { alert('adult'); } else { alert('teenager'); }
比较运算符
当我们对Number做比较时,可以通过比较运算符得到一个布尔值:
2 > 5; // false 5 >= 2; // true 7 == 7; // true
实际上,JavaScript允许对任意数据类型做比较:
false == 0; // true false === 0; // false
要特别注意相等运算符==
。JavaScript在设计时,有两种比较运算符:
第一种是==
比较,它会自动转换数据类型再比较,很多时候,会得到非常诡异的结果;
第二种是===
比较,它不会自动转换数据类型,如果数据类型不一致,返回false
,如果一致,再比较。
由于JavaScript这个设计缺陷,不要使用==
比较,始终坚持使用===
比较。
另一个例外是NaN
这个特殊的Number与所有其他值都不相等,包括它自己:
NaN === NaN; // false
唯一能判断NaN
的方法是通过isNaN()
函数:
isNaN(NaN); // true
最后要注意浮点数的相等比较:
1 / 3 === (1 - 2 / 3); // false
null
表示一个“空”的值,它和0
以及空字符串''
不同,0
是一个数值,''
表示长度为0的字符串,而null
表示“空”。
在其他语言中,也有类似JavaScript的null
的表示,例如Java也用null
,Swift用nil
,Python用None
表示。但是,在JavaScript中,还有一个和null
类似的undefined
,它表示==“未定义
”==。
JavaScript的设计者希望用null
表示一个空的值,而undefined
表示值未定义。事实证明,这并没有什么卵用,区分两者的意义不大。大多数情况下,我们都应该用null
。
undefined
仅仅在判断函数参数是否传递的情况下有用。
数组是一组按顺序排列的集合,集合的每个值称为元素。JavaScript的数组可以包括任意数据类型。例如:
[1, 2, 3.14, 'Hello', null, true];
上述数组包含6个元素。数组用[]
表示,元素之间用,
分隔。
另一种创建数组的方法是通过Array()
函数实现:
new Array(1, 2, 3); // 创建了数组[1, 2, 3]
然而,出于代码的可读性考虑,强烈建议直接使用[]
。
数组的元素可以通过索引来访问。请注意,索引的起始值为0
:
var arr = [1, 2, 3.14, 'Hello', null, true]; arr[0]; // 返回索引为0的元素,即1 arr[5]; // 返回索引为5的元素,即true arr[6]; // 索引超出了范围,返回undefined
JavaScript的对象是一组由键-值组成的无序集合,例如:
var person = { name: 'Bob', age: 20, tags: ['js', 'web', 'mobile'], city: 'Beijing', hasCar: true, zipcode: null };
JavaScript对象的键都是字符串类型,值可以是任意数据类型。上述person
对象一共定义了6个键值对,其中每个键又称为对象的属性,例如,person
的name
属性为'Bob'
,zipcode
属性为null
。
要获取一个对象的属性,我们用对象变量.属性名
的方式:
<script> var person = { name: 'Bob', age: 20, tags: ['js', 'web', 'mobile'], city: 'Beijing', hasCar: true, zipcode: null }; document.write(person.name); // 'Bob' document.write('<br>'); // 'Bob' document.write(person.zipcode); // null </script>
变量在JavaScript中就是用一个变量名表示,变量名是大小写英文、数字、$
和_
的组合,且不能用数字开头。变量名也不能是JavaScript的关键字,如if
、while
等。申明一个变量用var
语句,比如:
var a; // 申明了变量a,此时a的值为undefined var $b = 1; // 申明了变量$b,同时给$b赋值,此时$b的值为1 var s_007 = '007'; // s_007是一个字符串 var Answer = true; // Answer是一个布尔值true var t = null; // t的值是null
变量名也可以用中文,但是,请不要给自己找麻烦。
在JavaScript中,使用等号=
对变量进行赋值。可以把任意数据类型赋值给变量,同一个变量可以反复赋值,而且可以是不同类型的变量,但是要注意只能用var
申明一次,
例如:
var a = 123; // a的值是整数123 a = 'ABC'; // a变为字符串
这种变量本身类型不固定的语言称之为动态语言,与之对应的是静态语言。静态语言在定义变量时必须指定变量类型,如果赋值的时候类型不匹配,就会报错。
例如Java是静态语言,赋值语句如下:
int a = 123; // a是整数类型变量,类型用int申明 a = "ABC"; // 错误:不能把字符串赋给整型变量
和静态语言相比,动态语言更灵活,就是这个原因。
请不要把赋值语句的等号等同于数学的等号。
2、引用数据类型:对象
3、变量
概念:一小块存储数据的内存空间
==语法:var 变量名 = 初始化值;==
typeof 运算符 :获取变量的类型
注:null 运算后得到的是object
4、运算符
1.一元运算符:只有一个运算数的运算符 * ++(--) 在前,先自增(自减),再运算 * ++(--) 在后,先运算,再自增(自减) * +(-):正负号 * 注意:在JS中,如果运算数不是运算符所要求的类型,那么js引擎会自动的将运算数进行类型转换 * 其他类型转number: * string转number:按照字面值转换。如果字面值不是数字,则转为NaN(不是数字的数字) * boolean转number:true转为1,false转为0 2. 算数运算符 + - * / % ... 3. 赋值运算符 = += -+.... 4. 比较运算符 > < >= <= == ===(全等于) * 比较方式 1. 类型相同:直接比较 * 字符串:按照字典顺序比较。按位逐一比较,直到得出大小为止。 2. 类型不同:先进行类型转换,再比较 * ===:全等于。在比较之前,先判断类型,如果类型不一样,则直接返回false 5. 逻辑运算符 && || ! * 其他类型转boolean: 1. number:0或NaN为假,其他为真 2. string:除了空字符串(""),其他都是true 3. null&undefined:都是false 4. 对象:所有对象都为true 6. 三元运算符 ? : 表达式 var a = 3; var b = 4; var c = a > b ? 1:0; * 语法: * 表达式? 值1:值2; * 判断表达式的值,如果是true则取值1,如果是false则取值
5、流程控制语句
1. if...else... 2. switch: * 在java中,switch语句可以接受的数据类型: byte int short char,枚举(1.5) ,String(1.7) * switch(变量): case 值: * 在JS中,switch语句可以接受任意的原始数据类型 3. while 4. do...while 5. for
6、JS特殊语法:
1. 语句以;结尾,如果一行只有一条语句则 ;可以省略 (不建议) 2. 变量的定义使用var关键字,也可以不使用 * 用: 定义的变量是局部变量 * 不用:定义的变量是全局变量(不建议)
7、99乘法表
<script> for (var i = 1; i <=9; i++) { for (var j = 1; j <=i; j++) { document.write(i + "×" +j + "=" + (i*j) + "  "); } document.write('<br>'); } </script>
函数(方法)对象
1、创建:
1、 var fun = new Function(形式参数列表,方法体); //不建议使用 2、 function 方法名称(形式参数列表){ 方法体 } 3、 var 方法名 = function(形式参数列表){ 方法体 }
2、属性:
length:代表形参的个数
3、特点:
方法定义是,形参的类型不用写,返回值类型也不写。
方法是一个对象,如果定义名称相同的方法,会覆盖
在JS中,方法的调用只与方法的名称有关,和参数列表无关
在方法声明中有一个隐藏的内置对象(数组),arguments,封装所有的实际参数
4、调用:
方法名称(实际参数列表);
在JavaScript中,Date
对象用来表示日期和时间。
创建 Date 对象的语法:
var date=new Date()
**注释:**Date 对象会自动把当前日期和时间保存为其初始值。
要获取系统当前时间,用:
var date = new Date(); date; // 返回当日的日期和时间。 date.getFullYear(); // 从 date 对象以四位数字返回年份。 date.getMonth(); // 从 date 对象返回月份 (0 ~ 11)。 date.getDate(); // 从 date 对象返回一个月中的某一天 (1 ~ 31)。 date.getDay(); // 从 date 对象返回一周中的某一天 (0 ~ 6)。 date.getHours(); // 返回 date 对象的小时 (0 ~ 23)。 date.getMinutes(); // 返回 date 对象的分钟 (0 ~ 59)。 date.getSeconds(); // 返回 date 对象的秒数 (0 ~ 59)。 date.getMilliseconds(); // 返回 date 对象的毫秒(0 ~ 999)。 date.getTime(); // 返回 1970 年 1 月 1 日至今的毫秒数。 date.toLocaleString() //根据本地时间格式,把 date 对象转换为字符串。
其他Date对象的方法
注意:JavaScript的月份范围用整数表示是0~11,0
表示一月,1
表示二月……,所以要表示6月,我们传入的是5
!
JavaScript的Date对象月份值从0开始,牢记0=1月,1=2月,2=3月,……,11=12月。
1、正则表达式:定义字符串的组成规则
1、单个字符:[ ] 如:[a]、[ab]、[a-zA-Z0-9_] 特殊符号代表特殊含义的单个字符: \d : 单个数字字符 [0-9] \w : 单个单词字符 [a-zA-Z0-9_] 2、量词符号 ? :表示出现0次或1次 * :表示出现0次或多次 + :表示出现1次或多次 {m,n}:表示m<= 数量 <= n m如果缺省:{,n}:最多n次 n如果缺省:{m,}:最少m次 3、开始结束符号 ^ : 开始 $ : 结束
2、正则对象
1、创建 * var reg = new RegExp("正则表达式"); * var reg = /正则表达式/; 2、方法 * test(参数):验证指定的字符串是否符合正则定义的规范
预编译
JS解释器如何找到我们定义的函数和变量?
*通过 **变量对象(Variable Object, VO)*来获取。VO是一个抽象概念的“对象”,它用于存储执行上下文中的:
1. 变量;2. 声明;3. 函数参数。
函数的VO分为两个阶段——变量初始化和代码执行。在变量初始化阶段,VO按照如下顺序填充:
1. 函数参数(若未传入,初始化该参数值为undefined)
2. 函数声明(若发生命名冲突,会覆盖)
3. 变量声明(初始化变量值为undefined,若发生命名冲突,则忽略)
注意:函数表达式与变量初始化无关。
在变量初始化阶段,需要先对arguments变量进行初始化(激活对象,AO),再把函数体内的变量声明与函数声
明存储在AO内,VO(functionContext) === AO。
在函数执行的前一刻,他创造了一个空间,然后看了一眼函数,把我们马上要用到的 aa 放到了这个空间里面,这个过程就称为预编译
在函数执行之前将函数中的变量、方法收集起来,存放到一个空间中,以便函数在稍后执行时能从这个空间中
拿到函数中需要的变量和方法。而这个空间被称为执行期上下文,也叫活动对象(Activation Object),在后面都
称为 AO,他是一个对象。
总结:
预编译的的过程不是从上到下顺序执行的,并且,函数声明存放进 AO 的顺序在变量声明之后。
预编译发生在函数执行的前一刻!
预编译的过程(预编译四部曲): 1、创建 AO 对象(Activation Object)(执行期上下文) 2、找形参和变量声明,将变量和形参名作为 AO 属性名,值为 undefined 3、将实参值和形参统一 4、找函数声明,函数名作为 AO 属性名,值为函数体
例题1:
写出所有打印结果。
第一步创建 AO 对象
第二步找形参,变量声明,值为 undefined
第三步实参和形参统一
a是形参
第四步找函数声明,值为函数体
然后就是正常执行函数了,最后结果为
注意:var b = function(){} 他不是一个函数声明,是一个变量声明 + 赋值语句
例题2:
<script> function test(a) { console.log(a); var a = 123; console.log(a); function a() {} console.log(a); console.log(b); var b = function () {} console.log(b); function d() {} } test(1); </script>
1、创建AO对象 AO { } 2、 找形参和变量声明, 将变量和形参名作为AO属性名, 值为undefined AO { a : undefined //形参 b : undefined //变量声明 } 3、将实参值和形参统一 AO { a : 1 b : undefined } 4、 在函数体里面找函数声明, 值赋予函数体. AO { a : function a(){} b : function () {} d : function d() {} }
GO global object
1、找变量
2、找函数声明
3、执行
var a = 1; function a(){ console.log(2); } console.log(a); 输出:1
1、创建GO变量 AO { } 2、找变量 AO { a:undefined; } 3、找函数声明 AO { a:undefined ---> function a(){} ; } 4、赋值实参 AO { a:undefined ---> function a(){} ---> 1; }
GO === window
<script> function test(){ console.log(b); if(a){ var b =2; } c=3; console.log(c); } var a; test(); a=1; console.log(a); </script> 输出:undefined 3 1
GO={ a : undefined, --->1 test : function test() {} c:3 } AO={ b : undefined } if语句在预编译前是不执行的,所以b是在AO的 c=3; 没有var声明,所以在GO
特点:全局变量,这个Global中封装的方法不需要对象就可以直接调用。
方法名();
1、方法
encodeURI() : url编码 decodeURI() : url解码 encodeURIComponent() :url编码 decodeURIComponent() :url解码 parseInt(); //将字符串转为数字 //逐一判断每一个字符是否是数字,直到不是数字为止,将前边数字部分转为number isNaN(); //判断一个值是否是NaN eval(); //将JavaScrict 字符串,并把它作为脚本代码来执行。
encodeURI() 、decodeURI() 案例
URL编码 传智播客 = %E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2 <script> var str = "传智播客"; var encode = encodeURI(str); //url编码 document.write(encode+"<br/>"); var decode =decodeURI(str); //url解码 document.write(decode); </script> 结果: %E4%BC%A0%E6%99%BA%E6%92%AD%E5%AE%A2 传智播客
parseInt() 将字符串转为数字
var str2 = "234abc"; document.write(parseInt(str2)); 结果:234 若数字前面不是数字,即变成NaN var str2 = "a234abc"; document.write(parseInt(str2)); 结果:NaN
parseInt(str2,radix)表示进制转换
var str2 = '10'; console.log(parseInt(str2,16)); //将10转换为16进制的数 输出:16
<script> var str2 = parseFloat('3.1415926'); console.log(str2); </script> 输出:3.1415926
toFixed:保留小数点后几位(四舍五入)
<script> var str2 = parseFloat('3.1415926'); console.log(str2.toFixed(3)); </script> 输出:3.142
isNaN(); //判断一个值是否是NaN
转换为 Number(值) --> 再判断是否为NaN --> 再输出boolean值
<script> var a = "NaN"; document.write(a==NaN); document.write("<br/>"); document.write(isNaN(a)); </script> 结果: false true console.log(isNaN('a')); console.log(isNaN(null)); console.log(isNaN(undefined)); 输出:true,false,true
eval(); //将JavaScrict 字符串,并把它作为脚本代码来执行。
<script> var jscode = "alert(123)"; eval(jscode); </script> 结果:弹出123窗口
* 概念: Document Object Model 文档对象模型 * 将标记语言文档的各个组成部分,封装为对象。可以使用这些对象,对标记语言文档进行CRUD的动态操作 * W3C DOM 标准被分为 3 个不同的部分: * 核心 DOM - 针对任何结构化文档的标准模型 * Document:文档对象 * Element:元素对象 * Attribute:属性对象 * Text:文本对象 * Comment:注释对象 * Node:节点对象,其他5个的父对象 * XML DOM - 针对 XML 文档的标准模型 * HTML DOM - 针对 HTML 文档的标准模型
* 核心DOM模型: * Document:文档对象 1. 创建(获取):在html dom模型中可以使用window对象来获取 1. window.document 2. document 2. 方法: 1. 获取Element对象: 1. getElementById() : 根据id属性值获取元素对象。id属性值一般唯一 2. getElementsByTagName():根据元素名称获取元素对象们。返回值是一个数组 3. getElementsByClassName():根据Class属性值获取元素对象们。返回值是一个数组 4. getElementsByName(): 根据name属性值获取元素对象们。返回值是一个数组 2. 创建其他DOM对象: createAttribute(name) createComment() createElement() createTextNode() 3. 属性 * Element:元素对象 1. 获取/创建:通过document来获取和创建 2. 方法: 1. removeAttribute():删除属性 2. setAttribute():设置属性 * Node:节点对象,其他5个的父对象 * 特点:所有dom对象都可以被认为是一个节点 * 方法: * CRUD dom树: * appendChild():向节点的子节点列表的结尾添加新的子节点。 * removeChild() :删除(并返回)当前节点的指定子节点。 * replaceChild():用新节点替换一个子节点。 * 属性: * parentNode 返回节点的父节点。
Element:元素对象案例 方法案例: 1. removeAttribute():删除属性 2. setAttribute():设置属性 <body> <a>点我试一试</a> <input type="button" id="btn_set" value="设置属性"> <input type="button" id="btn_remove" value="删除属性"> <script> //获取btn var btn_set = document.getElementById("btn_set"); btn_set.onclick = function(){ //获取a标签 var element_a = document.getElementsByTagName("a")[0]; element_a.setAttribute("href","https://www.baidu.com"); } var btn_remove = document.getElementById("btn_remove"); btn_remove.onclick = function(){ //删除a标签 var element_a = document.getElementsByTagName("a")[0]; element_a.removeAttribute("href"); } </script> </body>
* appendChild():向节点的子节点列表的结尾添加新的子节点。 * removeChild() :删除(并返回)当前节点的指定子节点。 * replaceChild():用新节点替换一个子节点。 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> div { border: 1px solid red; } #div1 { width: 200px; height: 200px; } #div2 { width: 100px; height: 100px; } #div3 { width: 100px; height: 100px; } </style> </head> <body> <div id="div1"> <div id="div2">div2</div> div1 </div> <a href="javascript:void(0);" id="del">删除子节点</a> <a href="javascript:void(0);" id="add">增加子节点</a> <script> //1、获取超链接 var element = document.getElementById("del"); //2、绑定单击事件 element.onclick = function () { var div1 = document.getElementById("div1"); var div2 = document.getElementById("div2"); div1.removeChild(div2); } //1、获取超链接 var element_add = document.getElementById("add"); //2、绑定单击事件 element_add.onclick = function () { var div1 = document.getElementById("div1"); //给div1添加子节点 //创建div结点 var div3 = document.createElement("div"); div3.setAttribute("id", "div3"); div1.appendChild(div3); } </script> </body> </html>
href=”#”,包含了一个位置信息.默认的锚是#top,也就是网页的上端,当连续快速点击此链接时会导致浏览器巨慢甚至崩溃。而javascript:void(0) 仅仅表示一个死链接,没有任何信息。所以调用脚本的时候最好用void(0) href="#"与javascript:void(0)的区别 1、href="#"方法其实也是空连接的意思,但是点击之后会自动跳转到页面的最上面,因为用了这个方法就相当于点击了一个锚记,但是这个锚记又没写ID,所以就默认跳转到页面顶部。 2、#可以跳转到设置了id的目的地 3、javascript:void(0)则停留在原地,一动不动,我们称之为“死链接”
<!-- 1.当用户链接时,void(0)计算为0,用户点击不会发生任何效果 --> <a href="javascript:void(0);">单击此处什么都不会发生</a><br>
<!-- 2.执行 void() 操作符中的代码 --> <a href="javascript:void(alert('还真点啊你,真听话!!!哈哈哈!!!'))">点我弹出警告框!!!</a><br> <a href="javascript:void(console.log('还真点啊你,真听话!!!哈哈哈!!!'))">点我输出到控制台!!!</a><br>
<button type="button">点我</button> <script type="text/javascript"> document.querySelector('button').addEventListener('click', function () { var a, b, c, d; a = void(b = 2, c = 3); console.log('a => ' + a); console.log('b => ' + b); console.log('c => ' + c); console.log('d => ' + d); }); </script>
* HTML DOM 1. 标签体的设置和获取:innerHTML 2. 使用html元素对象的属性 3. 控制元素样式 1. 使用元素的style属性来设置 如: //修改样式方式1 div1.style.border = "1px solid red"; div1.style.width = "200px"; //font-size--> fontSize div1.style.fontSize = "20px"; 2. 提前定义好类选择器的样式,通过元素的className属性来设置其class属性值。
https://www.w3school.com.cn/jsref/dom_obj_event.asp
* 概念:某些组件被执行了某些操作后,触发某些代码的执行。 * 事件:某些操作。如: 单击,双击,键盘按下了,鼠标移动了 * 事件源:组件。如: 按钮 文本输入框... * 监听器:代码。 * 注册监听:将事件,事件源,监听器结合在一起。 当事件源上发生了某个事件,则触发执行某个监听器代码。
常见的事件:
1. onclick:单击事件 2. ondblclick:双击事件
1. onblur:失去焦点 -----一般用于表单验证 2. onfocus:元素获得焦点。
onload:一张页面或一幅图像完成加载。
1. onm ousedown 鼠标按钮被按下。 *定义方法时,定义一个形参,接受event对象 *event对象的button属性可以获取鼠标按钮键被点击了 2. onm ouseup 鼠标按键被松开。 3. onm ousemove 鼠标被移动。 4. onm ouseover 鼠标移到某元素之上。 5. onm ouseout 鼠标从某元素移开。
1. onkeydown 某个键盘按键被按下。 2. onkeyup 某个键盘按键被松开。 3. onkeypress 某个键盘按键被按下并松开。
1. onchange 域的内容被改变。 2. onselect 文本被选中。
1. onsubmit 确认按钮被点击。 * 可以阻止表单的提交 * 方法返回false则表单被阻止提交 2. onreset 重置按钮被点击。
Event对象
Event对象代表事件的状态,比如事件在其中发送的元素,键盘按键的状态、鼠标的位置、鼠标按钮的状态。
事件通常与函数结合使用,函数不会在事件发生前被执行!
满足案例要求
功能:控制html文档的内容
获取页面标签(元素)对象:Element
document.getElementById(“id值”):通过元素的id获取元素对象
操作Element对象:
修改属性值:
修改标签体内容:
属性:innerHTML
获取元素对象
使用innerHTML属性修改标签体内容
功能:某些组件被执行了某些操作后,触发某些代码的执行。
如何绑定事件
直接在html标签上,指定事件的属性(操作),属性值就是js代码
通过js获取元素对象,指定事件属性,设置一个函数
<body> <img id="light" src="img/off.gif" onclick="fun();"> <img id="light2" src="img/off.gif"> <script> function fun(){ alert('我被点了'); alert('我又被点了'); } function fun2(){ alert('咋老点我?'); } //1.获取light2对象 var light2 = document.getElementById("light2"); //2.绑定事件 light2.onclick = fun2; </script> </body>
Browser Object Model 浏览器对象模型
1. 与弹出框有关的方法: alert() 显示带有一段消息和一个确认按钮的警告框。 confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框。 * 如果用户点击确定按钮,则方法返回true * 如果用户点击取消按钮,则方法返回false prompt() 显示可提示用户输入的对话框。 * 返回值:获取用户输入的值
<script> var flag = confirm("您确定要退出吗?"); if(flag){ alert("欢迎再次光临!"); }else{ alert("手别抖"); } </script>
<script> var result = prompt("请输入用户名:"); alert(result); </script>
close() 关闭浏览器窗口。 * 谁调用我 ,我关谁 open() 打开一个新的浏览器窗口 * 返回新的Window对象
<body> <input id="openBtn" type="button" value="打开一个新窗口"/> <input id="closeBtn" type="button" value="关闭窗口"/> <script> var openBtn = document.getElementById('openBtn'); var newWindow; openBtn.onclick = function() { newWindow = open("https://www.baidu.com"); } var closeBtn = document.getElementById('closeBtn'); closeBtn.onclick = function() { newWindow.close(); } </script> </body>
setTimeout() 在指定的毫秒数后调用函数或计算表达式。 * 参数: 1. js代码或者方法对象 2. 毫秒值 * 返回值:唯一标识,用于取消定时器 clearTimeout() 取消由 setTimeout() 方法设置的 timeout。 setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式。 clearInterval() 取消由 setInterval() 设置的 timeout。
<script> function fun(){ alert('Boom'); } setInterval(fun,2000); </script>
<body> <img src="img/banner_1.jpg" id="img" width="100%"> <script> var number = 1; function fun() { number++; if (number > 3) { number = 1; } var img = document.getElementById("img"); img.src = "img/banner_" + number + ".jpg"; } setInterval(fun, 3000); </script> </body>
1. 获取其他BOM对象: history location Navigator Screen: 2. 获取DOM对象 document
* Window对象不需要创建可以直接使用 window使用。 window.方法名(); * window引用可以省略。 方法名();
地址栏对象
1. 创建(获取): 1. window.location 2. location 2. 方法: * reload() 重新加载当前文档。刷新 3. 属性 * href 设置或返回完整的 URL。
reload() 例子:
<body> <button id="btn" type="button" value="刷新">刷新</button> <script> var btn = document.getElementById('btn'); btn.onclick = function () { location.reload(); } </script> </body>
href 例子:
<body> <button id="goItcast" type="button" value="菜鸟教程">菜鸟教程</button> <script> var btn1 = document.getElementById('goItcast'); btn1.onclick = function () { location.href ="https://www.runoob.com/"; } </script> </body>
自动跳转页面
<style> p{ text-align: center; } span{ color:red; } </style> <body> <p><span id="time">5</span>秒后,页面自动跳转</p> <script> var second = 5; var time = document.getElementById("time"); function showtime() { second --; //判断时间如果<=0,则跳转页面 if (second<=0) { location.href ="https://www.runoob.com/"; } time.innerHTML = second +""; } //设置循环定时器,一秒执行一次该方法 setInterval(showtime,1000); </script> </body>
https://www.w3school.com.cn/htmldom/dom_intro.asp //W3教程
1、标签体的设置和获取:innerHTML
2、使用html元素对象的属性
3、控制元素样式
控制样式1:使用元素的style属性来设置
<body> <div id="div1"> div </div> <script> var div1 = document.getElementById('div1'); div1.onclick = function(){ //修改样式1 div1.style.border = '1px solid red'; div1.style.fontSize = '50px'; div1.style.width = '200px'; } </script> </body>
控制样式2:提前定义好选择器的样式,通过元素的className属性来设置其class属性值
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <style> .d2{ border: 1px solid blue; width:100px; } </style> </head> <body> <div id="div2"> div2 </div> <script> var div2 = document.getElementById('div2'); div2.onclick = function(){ div2.className="d2"; } </script> </body> </html>
事件代理(Event Delegation)又称之为事件委托。是Javascript中常用绑定事件的常用技巧。
“事件代理” 既是把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。
事件代理的原理是DOM元素的事件冒泡。
通俗例子: 比如一个宿舍的同学同时快递到了,一种方法就是他们一个个去领取,还有一种方法就是把这件事情委托给宿舍长,让一个人出去拿好所有快递,然后再根据收件人一 一分发给每个宿舍同学; 在这里,取快递就是一个事件,每个同学指的是需要响应事件的 DOM 元素,而出去统一领取快递的宿舍长就是代理的元素,所以真正绑定事件的是这个元素,按照收件人分发快递的过程就是在事件执行中,需要判断当前响应的事件应该匹配到被代理元素中的哪一个或者哪几个。
比如要给一个dom节点添加一个点击事件,但是现在事件不加在该dom节点本身,而是加在它的父节点身上,利用它父节点触发事件,给该dom节点实现事件效果
事件委托是利用事件的冒泡原理来实现的
事件从最深的节点开始,然后逐步向上传播事件
一个事件触发后,会在子元素和父元素之间传播(propagation)
事件传播分成三个阶段:
捕获阶段:从window对象传导到目标节点(上层传到底层)称为“捕获阶段”(capture phase),捕获阶段不会响应任何事件;
目标阶段:在目标节点上触发,称为“目标阶段”
冒泡阶段:从目标节点传导回window对象(从底层传回上层),称为“冒泡阶段”(bubbling phase)。事件代理即是利用事件冒泡的机制把里层所需要响应的事件绑定到外层;
冒泡例子: 页面上有这么一个节点树,div>ul>li>a;比如给最里面的a加一个click点击事件,那么这个事件就会一层一层的往外执行,执行顺序a>li>ul>div,有这样一个机制,那么我们给最外面的div加点击事件,让里面的ul,li,a实现事件效果,所以都会触发,这就是事件委托,委托它们父级代为执行事件。
例子1: <body> <ul id="ul"> <li>周一去游玩</li> <li>周二去上班</li> <li>周三去休息</li> <li>周四去吃饭</li> </ul> <!--利用事件委托给每一个li标签添加点击事件--> <script> var ul = document.querySelector("#ul"); ul.onclick = function(){ console.log("快醒醒,每天都要上班的!") } </script> </body>
例子1中利用父级ul
做事件处理,当li
被点击时,由于冒泡原理,事件就会冒泡到ul
上,因为ul
上有点击事件,所以事件就会触发。
例子2:事件代码不一样 <body> <ul id="ul"> <li>周一去游玩</li> <li class="work-day">周二去上班</li> <li>周三去休息</li> <li>周四去吃饭</li> </ul> <script> var ul = document.querySelector("#ul"); ul.onclick = function(e) { var e = event || window.event; var target = e.srcElement || e.target; if(target.className == "work-day"){ console.log("good boy") }else{ console.log("快醒醒,每天都要上班的!") } } </script> </body>
例子2中就会针对class属性等于"work-day"的li
元素做出不同的事件,其他事件则为默认事件
$(function () { $('#ul').on('click', 'li', function () { if ($(this).hasClass('work-day')) { alert("good boy"); } else { alert("快醒醒,每天都要上班的!"); } }) });
JSON.stringify()
的在作用是将JavaScript对象转换为JSON字符串而
JSON.parse()
可以将JSON字符串转为一个对象
let arr = [1,2,3]; JSON.stringify(arr); //'[1,2,3]' typeof JSON.stringify(arr); //string let string = '[1,2,3]' console.log(JSON.parse(string)) //[1,2,3] console.log(typeof JSON.parse(string)) //object
JSON.parse()
需要注意一点,由于此方法是将JSON字符串转换为对象,所以你的字符串必须符合JSON格式
,即键值都必须使用双引号包裹let a = '["1","2"]'; let b = "['1','2']"; console.log(JSON.parse(a)); //Array [1,2] console.log(JSON.parse(b)); //报错
1、判断数组是否包含某对象,或者判断对象是否相等
//判断数组是否包含某对象 let data = [ {name:'echo'}, {name:'听风是风'}, {name:'天子笑'}, ], val = {name:'天子笑'}; JSON.stringify(data).indexOf(JSON.stringify(val)) !== -1;//true //判断两数组/对象是否相等 let a = [1,2,3], b = [1,2,3]; JSON.stringify(a) === JSON.stringify(b);//true
2.让localStorage/sessionStorage可以存储对象。
//存 function setLocalStorage(key,val){ window.localStorage.setItem(key,JSON.stringify(val)); }; //取 function getLocalStorage(key){ let val = JSON.parse(window.localStorage.getItem(key)); return val; }; //测试 setLocalStorage('demo',[1,2,3]); let a = getLocalStorage('demo');//[1,2,3]
3、实现对象深拷贝
JSON.stringify()
与JSON.parse()
来实现深拷贝是很不错的选择//深拷贝 function deepClone(data) { let _data = JSON.stringify(data), dataClone = JSON.parse(_data); return dataClone; }; //测试 let arr = [1,2,3], _arr = deepClone(arr); arr[0] = 2; console.log(arr,_arr)//[2,2,3] [1,2,3]
这两者虽然都可以将目标值转为字符串,但本质上还是有区别的,比如
let arr = [1,2,3]; JSON.stringify(arr);//'[1,2,3]' arr.toString();//1,2,3
其次,JSON.stringify()的受众更多是对象,而toString()虽然可以将数组转为字符串,但并不能对{name:‘天子笑’}这类对象实现你想要的操作,它的受众更多是数字。
浅拷贝、深拷贝
假设B复制了A,当修改A时,看B是否会发生变化
浅拷贝:如果B也跟着变了,说明这是浅拷贝,拿人手短
深拷贝:如果B没变,那就是深拷贝,自食其力
接收一个函数作为参数,效果是可以将数组循环一遍,函数参数有三个入参,不返回任何数据
[].forEach((item, index, arr) => {})
参数
item 每次遍历时对应的数组的元素
index 每次遍历时对应的数组的下标
arr 被遍历的数组本身
返回值
使用场景
例子
const arr = ["张三", "罗翔", "张伟"]; arr.forEach((item, index, arr) => { console.log(item, index); }); // '张三' 0 // '罗翔' 1 // '张伟' 2
对数组进行筛选,接收一个方法作为参数,该方法的返回值为
true
时就将该元素添加进新的数组
[].filter((item, index, arr) => true)
参数
返回值
使用场景
例子
const arr = [1, 5, 9, 2, 3]; const newArr = arr.filter((item, index, c) => item > 4) console.log(newArr) //[5, 9]
对数组进行映射,传一个方法,该方法需要返回一个数据,然后将所有返回的数据组成一个数组
[].map((item, index, arr) => 对数据进行处理并返回)
参数
item
每次遍历时对应的数组的元素index
每次遍历时对应的数组的下标arr
被遍历的数组本身返回值
使用场景
例子
const arr = [ { name: "张三", age: 14 }, { name: "罗翔", age: 30 }, { name: "法外狂徒", age: 23 } ] const newArr = arr.map((item, index, c) => item.name) console.log(newArr); //['张三', '罗翔', '法外狂徒']
对数组进行遍历,传入一个方法作为参数,返回一个
true
或者false
,一旦有一条返回的true
则立即中止遍历
[].some((item, index, arr) => true)
参数
item
每次遍历时对应的数组的元素index
每次遍历时对应的数组的下标arr
被遍历的数组本身返回值
true
,所有数据都不符合条件返回false
使用场景
例子
const arr = [ { name: "张三", age: 14 }, { name: "罗翔", age: 50 }, { name: "张伟", age: 23 }, ] const hasZhangWei = arr.some((item, index, c) => item.name === "张伟") console.log(hasZhangWei); // true const hasLinSanXin = arr.some((item, index, c) => item.name === "林散心") console.log(hasLinSanXin); // false
对数组进行遍历,传入一个方法作为参数,返回一个
true
或者false
,一旦有一条返回的false
则立即中止遍历(和some相反)
[].every((item, index, arr) => true)
参数
item
每次遍历时对应的数组的元素index
每次遍历时对应的数组的下标arr
被遍历的数组本身返回值
ture
则返回true
,否则 false
使用场景
例子
const arr = [ { name: "张三", age: 14 }, { name: "罗翔", age: 50 }, { name: "张伟", age: 23 }, ]; const all18 = arr.every((item, index, c) => item.age > 18) console.log(all18); //false const all3 = arr.every((item, index, c) => item.age > 3) console.log(all3); //true
对数组进行遍历,传入一个方法作为参数,返回第一个符合条件的元素本身或者他的下标
(find 返回元素本身, findIndex 返回其下标)
[].find((item, index, arr) => true) [].findIndex((item, index, arr) => true)
参数
item
每次遍历时对应的数组的元素index
每次遍历时对应的数组的下标arr
被遍历的数组本身返回值
find
返回符合条件的元素本身,没有就返回 undefined
findIndex
返回符合条件的元素的下标,没有就返回 undefined
使用场景
undefined
例子
const arr = [ { name: "张三", age: 14 }, { name: "罗翔", age: 50 }, { name: "张伟", age: 23 }, ]; const person = arr.find((item, index, c) => item.name === '罗翔') console.log(person); // { name:"罗翔",age:50 } const i = arr.findIndex((item, index, c) => item.name === '罗翔') console.log(i); // 1
JavaScript中的字符串有一个length
属性,该属性可以用来获取字符串的长度:
const str = 'hello'; str.length // 输出结果:5
charAt()和charCodeAt()方法都可以通过索引来获取指定位置的值:
charAt() 方法可以返回指定位置的字符。其语法如下:
string.charAt(index)
index表示字符在字符串中的索引值:
const str = 'hello'; str.charAt(1) // 输出结果:e
我们知道,字符串也可以通过索引值来直接获取对应字符,那它和charAt()有什么区别呢?来看例子:
const str = 'hello'; str.charAt(1) // 输出结果:e str[1] // 输出结果:e str.charAt(5) // 输出结果:'' str[5] // 输出结果:undefined
可以看到,当index的取值不在str的长度范围内时,str[index]会返回undefined,而charAt(index)会返回空字符串;除此之外,str[index]不兼容ie6-ie8,charAt(index)可以兼容。
em, index, arr) => true)
**参数** * `item` 每次遍历时对应的数组的元素 * `index` 每次遍历时对应的数组的下标 * `arr` 被遍历的数组本身 **返回值** * 当有遍历的所有方法 `ture`则返回`true`,否则 `false` **使用场景** * 判断列表是否所有的元素都符合某个条件 **例子** * 列表里是否所有人年龄都大于 18 ?列表里是否所有人年龄都大于 3 ? ```js const arr = [ { name: "张三", age: 14 }, { name: "罗翔", age: 50 }, { name: "张伟", age: 23 }, ]; const all18 = arr.every((item, index, c) => item.age > 18) console.log(all18); //false const all3 = arr.every((item, index, c) => item.age > 3) console.log(all3); //true
对数组进行遍历,传入一个方法作为参数,返回第一个符合条件的元素本身或者他的下标
(find 返回元素本身, findIndex 返回其下标)
[].find((item, index, arr) => true) [].findIndex((item, index, arr) => true)
参数
item
每次遍历时对应的数组的元素index
每次遍历时对应的数组的下标arr
被遍历的数组本身返回值
find
返回符合条件的元素本身,没有就返回 undefined
findIndex
返回符合条件的元素的下标,没有就返回 undefined
使用场景
undefined
例子
const arr = [ { name: "张三", age: 14 }, { name: "罗翔", age: 50 }, { name: "张伟", age: 23 }, ]; const person = arr.find((item, index, c) => item.name === '罗翔') console.log(person); // { name:"罗翔",age:50 } const i = arr.findIndex((item, index, c) => item.name === '罗翔') console.log(i); // 1
JavaScript中的字符串有一个length
属性,该属性可以用来获取字符串的长度:
const str = 'hello'; str.length // 输出结果:5
charAt()和charCodeAt()方法都可以通过索引来获取指定位置的值:
charAt() 方法可以返回指定位置的字符。其语法如下:
string.charAt(index)
index表示字符在字符串中的索引值:
const str = 'hello'; str.charAt(1) // 输出结果:e
我们知道,字符串也可以通过索引值来直接获取对应字符,那它和charAt()有什么区别呢?来看例子:
const str = 'hello'; str.charAt(1) // 输出结果:e str[1] // 输出结果:e str.charAt(5) // 输出结果:'' str[5] // 输出结果:undefined
可以看到,当index的取值不在str的长度范围内时,str[index]会返回undefined,而charAt(index)会返回空字符串;除此之外,str[index]不兼容ie6-ie8,charAt(index)可以兼容。