前言:
学习B站UP主狂神说视频笔记整理视频链接
文章参考廖雪峰的官方网站
前端三要素:HTML(结构),CSS(展示),JavaScript(行为)
JavaScript(简称“JS”)
是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web页面的脚本语言而出名,但是它也被用到了很多非浏览器环境中,JavaScript
基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式(如函数式编程)风格
JavaScript的标准是ECMAScript 。截至 2012 年,所有浏览器都完整的支持ECMAScript 5.1,旧版本的浏览器至少支持ECMAScript 3 标准。2015年6月17日,ECMA国际组织发布了ECMAScript的第六版,该版本正式名称为 ECMAScript 2015,但通常被称为ECMAScript 6 或者ES2015。
ECMAScript是一种由Ecma国际通过ECMA-262标准化的脚本程序设计语言。这种语言在万维网上应用广泛,它往往被称为JavaScript或JScript,所以它可以理解为是JavaScript的一个标准,但实际上后两者是ECMA-262标准的实现和扩展
最新版本已经到es6版本~
但是大部分浏览器还只停留在支持es5代码上!
开发环境—线上环境,版本不一致
标签内写入JavaScript代码<head>
...
<script>
alert("helloJavaScript")
script>
head>
script标签可以放在head或body或页面的其他位置中,通常会放在head或body中
标签引入外部的JS文件<head>
...
<script src="js/hello.js">script>
head>
下`
JavaScript是门非常随意的语言,为了防止它的随意性产生的问题,通过设置use strict
检查代码
2.定义use strict
必须写在第一行
<script>
"use strict"
let i=1;
script>
在JavaScript中严格区分大小写
JS的注释符合和Java的注释符合相同,如下:
// 单行注释内容
/* 多行注释内容 */
JS的基本数据类型一共有五种,分别为数值类型(number)、字符串类型(string)、布尔类型(boolean)、undefined、null。
在JS中不区分整数和浮点数
说明 | 案例 |
---|---|
整数 | 123 |
浮点数 | 123.1 |
科学计数法 | 1.123e3 |
负数 | -99 |
NaN | not a number |
Infinity | 无穷大 |
注意点:
尽量避免使用浮点数进行运算,存在精度问题
1.JS中的字符串是基本数据类型,和Java中不同的是,JS中的字符串可以用单引号或双引号引起来。
<script>
var str1 = "Hello JS";
var str2 = 'Hello JS';
script>
2.注意转译字符\
<script>
var str1 = "Hello\'";//输入引号
var str2 = 'Hello \n JS'; //换行
script>
3.多行字符串编写,使用``
符号包裹
<script>
var str1 = `1234567
22222222222211111`;//与Java不同的是 不用+号连接
script>
4.模板字符串
<script>
var name= "秦疆";//定义模板
var hello="你好,${name}";//引入模板
script>
5.字符串长度
与Java一样,字符串具有不变性
<script>
var name= "秦疆";
console.log(name.length);
script>
6.截取字符串substring
<script>
var name= "HelloWord";
console.log(name.substring(1,3));
script>
布尔类型常用条件测试中,值为true和false
JS的复杂数据类型主要指对象 需要注意的是,在JS中,数组、函数也属于对象
Array 对象用于在单个的变量中存储多个值,可以包含任意类型的数据
(1)通过Array构造函数创建数组
例如,声明一个空数组:
var arr1 = new Array();
例如,声明一个指定初始值的数组:
var arr2 = new Array(88,"Hello" ,true , 100);
(2)通过数组直接量创建数组
例如,声明一个空数组:
var arr1 = [];
例如,声明一个指定初始值的数组:
var arr2 = [88,"Hello" ,true , 100];
提示:
arr.length
赋值,数组的长度就可以发生变化,数值较小元素就会丢失arr[0]=1;
"1" != 1
slice ()
截取Array的一部分,返回一个新数组,类似于String中的substringpush()
在尾部加入值,pop()
从尾部删除值unshift()
在头部加入值,shift()
在头部移除值sort()
可以对当前Array进行排序若干个键值对,在JavaScript中所有键都是字符串,值是任意类型
<script>
/*格式*/
var user={
name: "秦疆",
age: 12,
sex: "男"
}
script>
提示:
delete 对象属性名
动态删除属性hasOwnProperty()
判断一个属性是否是这个对象自身拥有的Map与Set是EC6的新特性
Map:KV键值对
<script>
"use strict"
//EC6新特性 Map Set
let map = new Map();
map.set("tom",123);//设置一个元素
console.log(map.get("tom"));//获取一个元素
map.delete("tom");//删除一个元素
script>
Set:无序不重复集合
<script>
"use strict"
//EC6新特性 Map Set
let set = new Set();
set.add("1");//添加
set.add("2");
set.delete("2");//删除一个元素
console.log(set.has("2"));//是否包含某个元素
script>
遍历数组
<script>
"use strict"
var arr=[3,4,5];
for (let x of arr){
console.log(x);
}
script>
遍历Map
<script>
"use strict"
var map = new Map( [["tom", 100],[ "jack",90],[ "haha",80]]);
for (let x of map){
console.log(x);
}
script>
遍历Set
<script>
"use strict"
let set = new Set([1,2,3]);
for (let x of set){
console.log(x);
}
script>
在JS中通过var声明变量
<script>
var a = 10; //声明变量,赋值为数值10
var b = true; //声明变量,赋值为布尔值true
var c = "Hello JS"; //声明变量,赋值为字符串"Hello JS"
script>
在JS中声明的变量不区分类型,可以指向任意的数据类型
<script>
var x = 10; //声明变量,赋值为数值10
x = true; //将x赋值为布尔值true
x = "Hello JS"; 将x赋值为字符串"Hello JS"
script>
在EC6中通过let
声明局部变量更加安全
<script>
let a= 10; //let声明变量
script>
JS和Java中的运算符大致相同
算术运算符: +,-,*,/,%,++,--
赋值运算符: =,+=,-=,*=,/=,%=
比较运算符: ==,!=,>,>=,<,<=
位运算符: & , |
逻辑运算符: && ,||
前置逻辑运算符: ! (not)
三元运算符: 表达式 ? 表达式 : 表达式
...
比较运算符(重要)
= 赋值
== 类型不一样 值一样 也会判断为true 1="1"
=== 类型一样 值一样才会判断为true
注意点:
===
比较NaN===NaNcy
与任何值比较都不相等 包括自己if分支结构用于基于不同的条件来执行不同的动作。语法结构如下:
if (条件 1){
当条件 1 为 true 时执行的代码
}else if (条件 2){
当条件 2 为 true 时执行的代码
}else{
当条件 1 和 条件 2 都不为 true 时执行的代码
}
使用 switch 语句来选择要执行的多个代码块之一。语法结构如下:
switch(n){
case 1:
执行代码块 1
break;
case 2:
执行代码块 2
break;
default:
与 case 1 和 case 2 不同时执行的代码
}
执行原理:首先设置表达式 n(通常是一个变量)。随后表达式的值会与结构中的每个 case 的值做比较。如果存在匹配,则与该 case 关联的代码块会被执行。请使用 break 来阻止代码自动地向下一个 case 运行。
for 循环的语法结构如下:
for (语句 1; 语句 2; 语句 3){
//被执行的代码块
}
JS中while循环也分为while和do/while循环,下面为while循环语法结构
while (条件){
//需要执行的代码
}
while 循环会在指定条件为真时循环执行代码块。
在JavaScript中,定义函数的方式如下:
function abs(x) {
if (x >= 0) {
return x;
} else {
return -x;
}
}
上述abs()
函数的定义如下:
function
指出这是一个函数定义;abs
是函数的名称;(x)
括号内列出函数的参数,多个参数以,分隔;{ ... }
之间的代码是函数体,可以包含若干语句,甚至可以没有任何语句。请注意,函数体内部的语句在执行时,一旦执行到return
时,函数就执行完毕,并将结果返回。因此,函数内部通过条件判断和循环可以实现非常复杂的逻辑。
如果没有return
语句,函数执行完毕后也会返回结果,只是结果为undefined
。
由于JavaScript的函数也是一个对象,上述定义的abs()
函数实际上是一个函数对象,而函数名abs
可以视为指向该函数的变量。
因此,第二种定义函数的方式如下:
var abs = function (x) {
if (x >= 0) {
return x;
} else {
return -x;
}
};
在这种方式下,function (x) { ... }
是一个匿名函数,它没有函数名。但是,这个匿名函数赋值给了变量abs,所以,通过变量abs就可以调用该函数。
上述两种定义完全等价,注意第二种方式按照完整语法需要在函数体末尾加一个;
,表示赋值语句结束。
调用函数时,按顺序传入参数即可:
abs(10); // 返回10
abs(-9); // 返回9
JS中允许传任意个参数,也可以不传递参数
abs(10, 'blablabla'); // 返回10
abs(-9, 'haha', 'hehe', null); // 返回9
abs(); // 返回NaN
参数进来是否存在问题?
假设不存在参数,如何进行规避?
function abs(x) {
//手动抛出异常来判断
if (typeof x !== 'number') {
throw 'Not a number';
}
if (x >= 0) {
return x;
} else {
return -x;
}
}
typeof
判断参数的类型
格式:
typeof x(参数)
JavaScript还有一个免费赠送的关键字arguments
,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array:
function foo(x) {
console.log('x = ' + x); // 10
for (var i=0; i<arguments.length; i++) {
console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
}
}
foo(10, 20, 30);
arguments包含所有的参数,有时我们只想使用多余的参数来进行附加操作,需要排除已有参数
ES6的新特性,获取除了已经定义的参数之外的参数
function aaa(a,b,...rest) {
console.log("a=>"+a);
console.log("b=>"+b);
console.log(rest);
}
在JavaScript中,用var申明的变量实际上是有作用域的。
如果一个变量在函数体内部申明,则该变量的作用域为整个函数体,在函数体外不可引用该变量:
'use strict';
function foo() {
var x = 1;
x = x + 1;
}
x = x + 2; // ReferenceError! 无法在函数体外引用变量x
ps:非要想实现的话,可以研究一下闭包
如果两个不同的函数各自申明了同一个变量,那么该变量只在各自的函数体内起作用。换句话说,不同函数内部的同名变量互相独立,互不影响:
'use strict';
function foo() {
var x = 1;
x = x + 1;
}
function bar() {
var x = 'A';
x = x + 'B';
}
由于JavaScript的函数可以嵌套,此时,内部函数可以访问外部函数定义的变量,反过来则不行:
'use strict';
function foo() {
var x = 1;
function bar() {
var y = x + 1; // bar可以访问foo的变量x!
}
var z = y + 1; // ReferenceError! foo不可以访问bar的变量y!
}
如果内部函数和外部函数的变量名重名怎么办?
function foo() {
var x = 1;
function bar() {
var x = 'A';
console.log('x in bar() = ' + x); // 'A'
}
console.log('x in foo() = ' + x); // 1
bar();
}
foo();
这说明JavaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量。
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
'use strict';
function foo() {
var x = 'Hello, ' + y;
console.log(x);
var y = 'Bob';
}
foo();
运行结果会发现:y=undefined
这正是因为JavaScript引擎自动提升了变量y的声明,但不会提升变量y的赋值。
对于上述foo()函数,JavaScript引擎看到的代码相当于:
function foo() {
var y; // 提升变量y的申明,此时y为undefined
var x = 'Hello, ' + y;
console.log(x);
y = 'Bob';
}
由于JavaScript的这一怪异的“特性”,我们在函数内部定义变量时,请严格遵守“在函数内部首先申明所有变量”这一规则。最常见的做法是用一个var申明函数内部用到的所有变量:
function foo() {
var
x = 1, // x初始化为1
y = x + 1, // y初始化为2
z, i; // z和i为undefined
// 其他语句:
for (i=0; i<100; i++) {
...
}
}
不在任何函数内定义的变量就具有全局作用域。实际上,JavaScript默认有一个全局对象window
,全局作用域的变量实际上被绑定到window
的一个属性:
"use strict"
//全局变量
var x ="helloWord";
function foo() {
alert(x);
alert(window.x);//默认所有全局变量都会绑定到window对象上
}
alert()这个函数本身也是一个window
变量
"use strict"
//全局变量
var old =window.alert;
old(123);
window.alert=function () {
}
window.alert(345);//失效
window.alert=old;//恢复
window.alert(678);
你可能猜到了,由于函数定义有两种方式,以变量方式var foo = function () {}
定义的函数实际上也是一个全局变量,因此,顶层函数的定义也被视为一个全局变量,并绑定到window
对象:
'use strict';
function foo() {
alert('foo');
}
foo(); // 直接调用foo()
window.foo(); // 通过window.foo()调用
Javascript 实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,报错RefrenceError
规范
由于我们所有的全局变量都会绑定到我们的 window
上,如果不同的js 文件,使用了相同的全局变量,就会引发冲突~>如果能够减少冲突?
"use strict"
//唯一全局变量 不绑定到window上
var listapp={
};
//定义全局变量
listapp.name="王根基";
//定义函数
listapp.app=function (x) {
}
把自己的代码全部放入自己定义的唯一空问名字中,降低全局命名冲突的问题–
由于JavaScript的变量作用域实际上是函数内部,我们在for循环等语句块中是无法定义具有局部作用域的变量的:
'use strict';
function foo() {
for (var i=0; i<100; i++) {
//
}
i += 100; // 仍然可以引用变量i
}
为了解决块级作用域,ES6引入了新的关键字let
,用let
替代var
可以申明一个块级作用域的变量:
'use strict';
function foo() {
var sum = 0;
for (let i=0; i<100; i++) {
sum += i;
}
// SyntaxError:
i += 1;
}
由于var
和let
申明的是变量,如果要申明一个常量,在ES6之前是不行的,我们通常用全部大写的变量来表示“这是一个常量,不要修改它的值”:
var PI = 3.14;
ES6标准引入了新的关键字const
来定义常量,const
与let
都具有块级作用域:
'use strict';
const PI = 3.14;
PI = 3; // 某些浏览器不报错,但是无效果!
PI; // 3.14
在一个对象中绑定函数,称为这个对象的方法
在JavaScript中,对象的定义是这样的:
var xiaoming = {
name: '小明',
birth: 1990
};
但是,如果我们给xiaoming绑定一个函数,就可以做更多的事情。比如,写个age()
方法,返回xiaoming的年龄:
var xiaoming = {
name: '小明',
birth: 1990,
age: function () {
var y = new Date().getFullYear();
return y - this.birth;
}
};
xiaoming.name; // 调用属性
xiaoming.age(); // 调用方法必须得带括号
它在内部使用了一个this关键字,这个东东是什么?
一个方法内部,this
是一个特殊变量,它始终指向当前对象,也就是xiaoming
这个变量。
让我们拆开写:
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25, 正常结果
getAge(); // NaN
单独调用函数getAge()怎么返回了NaN?请注意,我们已经进入到了JavaScript的一个大坑里。
JavaScript的函数内部如果调用了this,那么这个this到底指向谁?
答案是,视情况而定!
如果以对象的方法形式调用,比如xiaoming.age()
,该函数的this
指向被调用的对象,也就是xiaoming
,这是符合我们预期的。
如果单独调用函数,比如getAge()
,此时,该函数的this
指向全局对象,也就是window
。
apply
在js中可以控制this
的指向
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空
时间函数
基本使用:
"use strict"
let dat = new Date();
dat.getFullYear();//年份
dat.getMonth();//月份 0-11 代表月
dat.getDate();//日期
dat.getDay();//星期几
dat.getHours();//时
dat.getMinutes()//分
dat.getSeconds();//秒
dat.getTime();//时间戳 全世界统一 1970
转换:
JSON(JavaScript Object Notation, JS 对象标记) 是一种轻量级的数据交换格式,目前使用特别广泛。
在JavaScript一切皆为对象、任何js支持的类型都可以用JSON来表示;number,string…
格式:
javascript中使用JSON
//编写一个javascript 对象
var user= {
name: "秦疆",
age: 3,
sex: "男"
}
//将js对象转换成JSON
var jsonuser = JSON.stringify(user);
//将JSON字符串转换成JS对象
var parse = JSON.parse(jsonuser);
console.log(parse);
JavaScript的面向对象编程和大多数其他语言如Java、C#的面向对象编程都不太一样。如果你熟悉Java或C#,很好,你一定明白面向对象的两个基本概念:
类:类是对象的类型模板,例如,定义Student
类来表示学生,类本身是一种类型,Student
表示学生类型,但不表示任何具体的某个学生;
实例:实例是根据类创建的对象,例如,根据Student
类可以创建出xiaoming、xiaohong、xiaojun等多个实例,每个实例表示一个具体的学生,他们全都属于Student
类型。
所以,类和实例是大多数面向对象编程语言的基本概念。
不过,在JavaScript中,这个概念需要改一改。JavaScript不区分类和实例的概念,而是通过原型(prototype)
来实现面向对象编程。
原型是指当我们想要创建xiaoming
这个具体的学生时,我们并没有一个Student
类型可用。那怎么办?恰好有这么一个现成的对象:
var robot = {
name: 'Robot',
height: 1.6,
run: function () {
console.log(this.name + ' is running...');
}
};
我们看这个robot
对象有名字,有身高,还会跑,有点像小明,干脆就根据它来“创建”小明得了!
于是我们把它改名为Student
,然后创建出xiaoming
:
var Student = {
name: 'Robot',
height: 1.2,
run: function () {
console.log(this.name + ' is running...');
}
};
var xiaoming = {
name: '小明'
};
//原型 小明指向Student
xiaoming.__proto__ = Student;
注意最后一行代码把xiaoming
的原型指向了对象Student
,看上去xiaoming
仿佛是从Student
继承下来的:
xiaoming.name; // '小明'
xiaoming.run(); // 小明 is running...
xiaoming
有自己的name
属性,但并没有定义run()
方法。不过,由于小明是从Student
继承而来,只要Student
有run()
方法,xiaoming
也可以调用:
JavaScript的原型链和Java的Class区别就在,它没有“Class”的概念,所有对象都是实例,所谓继承关系不过是把一个对象的原型指向另一个对象而已。
什么是原型链?
在JavaScript中,每个函数都有一个prototype属性,这个属性指向函数的原型对象。
当我们用obj.xxx
访问一个对象的属性时,JavaScript引擎先在当前对象上查找该属性,如果没有找到,就到其原型对象上找,如果还没有找到,就一直上溯到Object.prototype
对象,最后,如果还没有找到,就只能返回undefined
。
举个栗子~!
建一个Array
对象:
var arr = [1, 2, 3];
其原型链是:
arr ----> Array.prototype ----> Object.prototype ----> null
Array.prototype定义了indexOf()、shift()
等方法,因此你可以在所有的Array对象上直接调用这些方法。
当我们创建一个函数时:
function foo() {
return 0;
}
函数也是一个对象,它的原型链是:
foo ----> Function.prototype ----> Object.prototype ----> null
由于Function.prototype定义了apply()
等方法,因此,所有函数都可以调用apply()
方法。
很容易想到,如果原型链很长,那么访问一个对象的属性就会因为花更多的时间查找而变得更慢,因此要注意不要把原型链搞得太长。
在上面的章节中我们看到了JavaScript的对象模型是基于原型实现的,特点是简单,缺点是理解起来比传统的类-实例模型要困难,最大的缺点是继承的实现需要编写大量代码,并且需要正确实现原型链。
新的关键字class
从ES6开始正式被引入到JavaScript中。class的目的就是让定义类更简单。
用新的class
关键字来编写Student
,可以这样写:
class Student {
//构造器
constructor(name) {
this.name = name;
}
hello() {
alert('Hello, ' + this.name + '!');
}
}
//使用
let student = new Student("王根基");
student.hello();
用class定义对象的另一个巨大的好处是继承更方便了。现在,原型继承的中间对象,原型对象的构造函数等等都不需要考虑了,直接通过extends
来实现:
class xiaomin extends Student{
constructor(name,age){
//必须调用父类的构造器 否则会报错
super(name);
this.age=age;
}
helloword(){
alert("name:"+this.name+"age:"+this.age);
}
}
BOM:浏览器对象模型
JavaScript和浏览器关系?
JavaScript 诞生就是为了能够让他在浏览器中运行!
window
对象不但充当全局作用域,而且表示浏览器窗口。
window
对象有innerWidth
和innerHeight
属性,可以获取浏览器窗口的内部宽度和高度。内部宽高是指除去菜单栏、工具栏、边框等占位元素后,用于显示网页的净宽高。
兼容性:IE<=8不支持。
window.innerHeight
//210 内部宽度
window.innerWidth
//1280 内部高度
window.outerWidth
//1280
window.outerHeight
//690
还有一个outerWidth
和outerHeight
属性,可以获取浏览器窗口的整个宽高。
navigator
对象表示浏览器的信息,最常用的属性包括:
大多数时候,我们不会使用navigator
对象,因为会被人为修改!
不建议使用这些属性来判断和修改代码
screen
对象表示屏幕的信息,常用的属性有:
screen.width
// 1280
screen.height
// 720
screen.colorDepth
// 24
location
对象表示当前页面的URL信息。
要加载一个新页面,可以调用location.assign()
。如果要刷新当前页面,调用location.reload()
方法非常方便。
location.reload();//刷新页面
location.assign('https://www.bilibili.com/video/BV1JJ41177di?p=19');//加载新页面
document
对象表示当前页面。由于HTML在浏览器中以DOM形式表示为树形结构,document
对象就是整个DOM树的根节点。
获取具体的文档树根节点
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HelloScripttitle>
head>
<body>
<dl id="app">
<dt>Javadt>
<dd>JavaEEdd>
<dd>JavaSEdd>
dl>
<script>
var dl= document.getElementById('app');
script>
body>
html>
JavaScript可以通过document.cookie
读取到当前页面的Cookie
:
document.cookie; // 'v=123; remember=true; prefer=zh'
由于JavaScript能读取到页面的Cookie
,而用户的登录信息通常也存在Cookie
中,这就造成了巨大的安全隐患,这是因为在HTML页面中引入第三方的JavaScript代码是允许的
Cookie安全性问题
为了解决这个问题,服务器在设置Cookie
时可以使用httpOnly
,设定了httpOnly
的Cookie
将不能被JavaScript
读取。这个行为由浏览器实现,主流浏览器均支持httpOnly
选项,IE从IE6 SP1开始支持。
为了确保安全,服务器端在设置Cookie
时,应该始终坚持使用httpOnly
。
history对象保存了浏览器的历史记录,JavaScript可以调用history对象的back()
或forward ()
,相当于用户点击了浏览器的“后退”或“前进”按钮。
history.back();//后退
history.forword();//前进
核心
由于HTML文档被浏览器解析后就是一棵DOM树,要改变HTML的结构,就需要通过JavaScript来操作DOM。
始终记住DOM是一个树形结构。操作一个DOM节点实际上就是这么几个操作:
更新:更新该DOM节点的内容,相当于更新了该DOM节点表示的HTML的内容;
遍历:遍历该DOM节点下的子节点,以便进行进一步操作;
添加:在该DOM节点下新增一个子节点,相当于动态增加了一个HTML节点;
删除:将该节点从HTML中删除,相当于删掉了该DOM节点的内容以及它包含的所有子节点。
在操作一个DOM节点前,我们需要通过各种方式先拿到这个DOM节点。
最常用的方法是document.getElementById()
和document.getElementsByTagName()
,以及CSS选择器document.getElementsByClassName()
。
//标签选择器
let h1 = document.getElementsByTagName("h1");
//id选择器
let p1 = document.getElementById("p1");
//class选择器
let p2 = document.getElementsByClassName("p2");
let fals = document.getElementById("fals");
let children = fals.children;//获取父节点下的所有子节点
// fals.firstChild;获取第一个节点
// fals.lastChild; 获取最后一个节点
这是原生代码,以后都会使用Jquery
<body>
<div id="fals">
div>
<script>
let fals = document.getElementById("fals");
//修改文本的值
fals.innerText="123";
//修改超文本
fals.innerHTML="123";
//操作CSS
fals.style.color="steelblue";
fals.style.fontSize="200px";//注意驼峰命名
script>
body>
注意点:属性使用字符串包裹
要删除一个节点,首先要获得该节点本身以及它的父节点,然后,调用父节点的removeChild
把自己删掉:
//拿到待删除节点
let dl123 = document.getElementById("dl123");
//拿到父节点
let parent = dl123.parentElement;
//删除
let delt = parent.removeChild(dl123);
注意到删除后的节点虽然不在文档树中了,但其实它还在内存中,可以随时再次被添加到别的位置。
使用children
可以获取到父节点下所有子节点,它是一个数组可以通过下标获取节点fals.children[1]
当我们用如下代码删除子节点时:
var parent = document.getElementById('parent');
parent.removeChild(parent.children[0]);
parent.removeChild(parent.children[1]); // <-- 浏览器报错
浏览器报错: Firstparent.children[1]
不是一个有效的节点。原因就在于,当
节点被删除后,parent.children
的节点数量已经从2
变为了1
,索引[1
]已经不存在了。
当我们获得了某个DOM节点,想在这个DOM节点内插入新的DOM,应该如何做?
如果这个DOM节点是空的,例如,,那么,直接使用
innerHTML = 'child'
就可以修改DOM节点的内容,相当于“插入”了新的DOM节点。
如果这个DOM节点不是空的,那就不能这么做,因为innerHTML
会直接替换掉原来的所有子节点。
有两个办法可以插入新的节点。
使用appendChild
,把一个已有的子节点添加到父节点的最后一个子节点
<body>
<p id="js">JavaScriptp>
<div id="list">
<p id="se">javasep>
<p id="ee">javaeep>
<p id="me">javamep>
div>
<script>
let js = document.getElementById("js");
let list = document.getElementById("list");
// 追加到div最后面
list.appendChild(js);
script>
body>
//创建方式一:
let newp = document.createElement("p");
newp.id="newp";
newp.innerText="helloword";
//插入到div最后面
list.appendChild(newp);
//创建方式二
let myscript = document.createElement("script");
//万能设置值的方式setAttribute
myscript.setAttribute("type","text/javascript");
//插入到div最后面
list.appendChild(myscript);
//创建style标签
let mystyle = document.createElement("style");
//设置CSS样式
mystyle.setAttribute("type","text/css");
mystyle.innerText="body{\n" +
" background: steelblue;\n" +
" }";
//获取head标签
let myhead = document.getElementsByTagName("head")[0];
//插入到子后面
myhead.appendChild(mystyle);
如果我们要把子节点插入到指定的位置怎么办?
可以使用parentElement.insertBefore(插入节点, 在哪个节点前插入);
//获取div节点
let list = document.getElementById("list");
let ee = document.getElementById("ee");
let js = document.getElementById("js");
list.insertBefore(js,ee);
用JavaScript操作表单和操作DOM是类似的,因为表单本身也是DOM树。
不过表单的输入框、下拉框等可以接收用户输入,所以用JavaScript来操作表单,可以获得用户输入的内容,或者对一个输入框设置新的内容。
HTML表单的输入控件主要有以下几种:
文本框,对应的,用于输入文本;
口令框,对应的,用于输入口令;
单选框,对应的,用于选择一项;
复选框,对应的,用于选择多项;
下拉框,对应的,用于选择一项;
隐藏文本,对应的, 用户不可见,但表单提交时会把隐藏文本发送到服务器。
如果我们获得了一个节点的引用,就可以直接调用value获得对应的用户输入值:
//
var input = document.getElementById('email');
input.value; // '用户输入的值'
这种方式可以应用于text
、password
、hidden
以及select
。
对于单选框和复选框,value
属性返回的永远是HTML
预设的值,而我们需要获得的实际是用户是否“勾上了”选项,所以应该用checked
判断:
//
//
var mon = document.getElementById('monday');
var tue = document.getElementById('tuesday');
mon.value; // '1'
tue.value; // '2'
mon.checked; // true或者false
tue.checked; // true或者false
设置值和获取值类似,对于text
、password
、hidden
以及select
,直接设置value就可以:
//
var input = document.getElementById('email');
input.value = 'test@example.com'; // 文本框的内容已更新
对于单选框和复选框,设置checked
为true
或false
即可。
提交表单时 MD5对密码加密
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HelloScripttitle>
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js">script>
head>
<body>
<div id="div123">
<form action="#" method="post" onsubmit="return dist()">
<p>
<span>用户名:span><input type="text" name="username" id="name1">
p>
<p>
<span>密码:span><input type="password" id="pwd">
p>
<input type="hidden" name="md5-password" id="password">
<input type="submit" value="提交">
form>
div>
<script>
function dist() {
let username = document.getElementById("name1").value;
let pwd = document.getElementById("pwd").value;//获取输入密码
let password = document.getElementById("password");//获取隐藏域
password.value =md5(pwd);//MD5加密
alert(password.value);
//可以校验表单内容 true就是通过提交 false就是阻止提交
return false;
}
script>
body>
html>
JavaScript世界中使用最广泛的一个库。
使用jQuery只需要在页面的引入jQuery文件即可:
<html>
<head>
//本地
<script src="//code.jquery.com/jquery-1.11.3.min.js">script>
//CDN
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js">script>
...
head>
<body>
...
body>
html>
$ 是著名的jQuery符号。实际上,jQuery把所有功能全部封装在一个全局变量jQuery中,而$也是一个合法的变量名,它是变量jQuery的别名
window.jQuery; // jQuery(selector, context)
window.$; // jQuery(selector, context)
$ === jQuery; // true
typeof($); // 'function'
<html lang="en">
<head>
<meta charset="UTF-8">
<title>HelloScripttitle>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.0/jquery.js">script>
head>
<body>
<a href="" id="test-jqury">点击a>
<script>
//点击事件
$("#test-jqury").click(function () {
alert("helloJqury")
})
script>
body>
html>
首先请看原生JS选择器
//id选择器
document.getElementById();
//类
document.getElementsByClassName();
//标签选择器
document.getElementsByTagName();
原生JS代码中,选择器复杂且类型较少
在Jquery中 CSS代码的选择器 它全部都能用
//jQuery css 中的选择器它全部都能用!
$('p' ).click();//标签选择器
$( '#id1' ).click(); //id选择器
$( '.class1 ' ).click() //cLass选择器
Jquery文档工具站
因为JavaScript在浏览器中以单线程模式运行,页面加载后,一旦页面上所有的JavaScript代码被执行完后,就只能依赖触发事件来执行JavaScript代码。
浏览器在接收到用户的鼠标或键盘输入后,会自动在对应的DOM节点上触发相应的事件。如果该节点已经绑定了对应的JavaScript处理函数,该函数就会自动调用。
//当网页元素加载完毕之后 响应事件
$(function () {
//获取鼠标移动事件
$("#mouseMove").mousemove(function (e) {
$("#mouseMove").text("x"+e.pageX+"Y:"+e.pageY);
})
});
/*节点文本操作*/
$(function () {
//操作文本
$("#text-u1 li[class=js]").text();//获取值
$("#text-u1 li[class=js]").text("JavaSE");//设置值
//操作html
$("#text-u1 li[name=python]").html();//获取html
$("#text-u1 li[name=python]").html("mmm ");//设置值
});