目录
进度来源:尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版
网址:尚硅谷JavaScript基础&实战丨JS入门到精通全套完整版_哔哩哔哩_bilibili
一、JavaScript基础知识
JavaScript包含三个部分:
- ECMAScript:JavaScript标准
- DOM:文档对象模型,可以操作网页
- BOM:浏览器对象模型,提供一组对象,可以操作浏览器
二、3个基本语法:alert、console.log、document.write
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 引入外部js文件,引入外部后,此script标签内部不在生效 -->
<script type="text/javascript" src="./script.js"></script>
<!-- JS代码需要编写到script标签中,加不加type="text/javascript"都可 -->
<script type="text/javascript">
//单行注释
/*
* 控制浏览器弹出一个警告
* 点击警告的确定后,下面的代码才会执行
*/
alert("我是内部警告!");
/*
* 让计算机在body中写一段内容
*/
document.write("随便写点什么");
/*
* 向控制台输出一个内容
*/
console.log("控制台");
/*
* 输入框,返回值为字符串
* 想要数字需要强制类型转换
*/
// let a = prompt('请输入一个值:');
let a = +prompt('请输入一个值:');
</script>
</head>
<body>
<!-- 不推荐使用 -->
<!-- 将js代码编写到标签的onclick属性中 -->
<button onclick="alert('你点我干嘛~');">点我一下</button>
<!-- 将js代码编写到超链接的href属性中,点击时不会跳转 -->
<a href="javascript:alert('不要随便点我');">不要点我</a>
<a href="javascript:;">点完后不会有反映</a>
</body>
</html>
!!!JavaScript语法严格区分大小写
!!!每句结尾必加英文分号
三、数据类型、强制转换
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
/*
* 字面量:不可改变的值
* 变量:可以改变的值
*/
// 声明变量,并赋值
let a;
a = 123;
let b = 456;
console.log(a, b);
/*
* 标识符:变量名、函数名、属性名等
* 命名规则:
* 1.可含有字母、数字、_、$
* 2.不能以数字开头
* 3.不能是JS的关键字
* 4.命名规则一般为驼峰命名法,首字母小写,每个开头字母大写
* 5.JS由unicode编写,理论上所有utf-8含有的内容都可以用来命名,比如中文
*/
let a_1_$ = 789;
console.log(a_1_$)
/*
* JS的6种数据类型
* String 字符串(\可转义)
* Number 数值
* Boolean 布尔值
* Null 空值
* Undefined 未定义
* Object 对象
* 前五种基本数据类型,Object属于引用数据类型
*/
// \转义符,\n换行,\t一个tab
let str1 = "hello";
let str2 = 'hello';
let str3 = "hey! \"\n\t";
console.log(str1, str2, str3);
// typeof 输出变量类型
// Number.MAX_VALUE最大值,Number.MIN_VALUE正数最小值
// Infinity表示无穷,NaN表示非数字
let num1 = 123;
let num2 = Infinity;
let num3 = NaN;
console.log(num1, typeof num1);
console.log(Number.MAX_VALUE, Number.MIN_VALUE);
console.log(num2, typeof num2, num3, typeof num3);
// 布尔true or false
let bool1 = true;
console.log(bool1);
// null表示为空的对象
let null1 = null;
console.log(null1, typeof null1);
// 声明一个变量,但不赋值,就会undefined
let undefined1;
console.log(undefined1, typeof undefined1);
/*
* 强制类型转换:将一个数据类型转换为其他数据类型
* 一般都是转换为String和Number或Boolean
*/
// 1.调用toString方法,注意null和undefined无法转String
// 2.调用String函数
let num2str1 = 123;
num2str1 = num2str1.toString();
console.log(typeof num2str1);
let num2str2 = 456;
num2str2 = String(num2str2);
console.log(typeof num2str2);
// 1.调用Number函数,纯数字/空字符串/布尔/null会转,非全数字/undefined会转为NaN
// 2.调用parseInt函数或parseFloat函数,将变量先转为String再转为数字
let str2num1 = '123';
str2num1 = Number(str2num1);
console.log(typeof str2num1);
let str2num2 = '456p';
str2num2 = parseInt(str2num2);
console.log(typeof str2num2);
// 非零/非null对象转true,零/空/null/undefined转false
let other2bool = 123;
other2bool = Boolean(other2bool);
console.log(typeof other2bool);
</script>
</head>
<body>
</body>
</html>
四、运算符
<!DOCTYPE html>
<html lang="en">
<body>
</body>
</html>
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
/*
* 加法运算符+:优先级String > Number
* 除加法运算符外:优先级Number最大
* 运算自左向右进行
* 一元运算符:typeof、+(任意数据类型转Number)、-
* 自增和自减:++、--
* 逻辑运算符:!、&&、||,布尔值的运算结果为Boolean类型,非布尔计算结果:
* 与运算:
* 1. 第一个值为true,返回第二个值
* 2. 第一个值为false,返回第一个值
* 或运算:
* 1. 第一个值为true,返回第一个值
* 2. 第一个值为false,返回第二个值
* 相等运算符:==会进行类型转化,转为Number,===不进行类型转换
*/
</script>
</head>
五、条件判断、循环语句
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
// 代码块{},var无隔离作用,let有隔离作用
{
alert('hello');
console.log('nihao');
var a = 123;
let b = 456;
}
// a不报错,b报错
// console.log(a, b);
// 条件判断if,if中不能使用break和continue
if(1 == 2){
console.log(123);
}else if(1 == 1){
console.log(456);
}else{
console.log(789);
}
// 条件分支语句switch,num与case后的值全等比较,均为false执行default
let num = 2;
switch(num){
case 1:{
console.log(123);
break;
}
case 2:{
console.log(456);
break;
}
default:{
console.log(789);
}
}
// 循环语句while
let n = 1;
while(n < 50){
document.write(n++ + '<br />');
}
// 循环语句for
let m = 1;
for(; m < 10; m++){
console.log(m);
}
// 计时器
console.time('test');
console.timeEnd('test');
</script>
</head>
<body>
</body>
</html>
六、对象、对象字面量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script type="text/javascript">
/*
* 对象分类:
* 1.内建对象,ES标准中定义的,比如Math、String、Boolean
* 2.宿主对象,由JS运行环境提供的对象,目前主要指由浏览器提供的对象,比如BOM、DOM
* 3.自定义对象,开发人员自己定义的
*/
// 创建对象
let obj1 = new Object();
console.log(typeof obj1);
// 添加属性,中括号里可以传变量,属性值可以是任意类型,甚至是对象
obj1.name = '张三';
obj1.gender = 'male';
obj1.age = 18;
obj1['123'] = 456
console.log(obj1.age, obj1['123']);
console.log('age' in obj1, '123' in obj1);
// 对象是引用数据类型,内存地址一样,改一个都改
// 基本数据类型保存在栈内存,引用数据类型保存在堆内存(栈内存中保存对象的内存地址)
let obj2 = obj1;
obj1.age = 19;
console.log(obj2.age);
// 对象字面量创建
let obj3 = {
name: '张三',
age: 28,
test: {name: '李四'}
}
// 枚举对象属性
for(let n in obj3){
// n是属性名
console.log(n, obj3[n]);
}
</script>
</head>
<body>
</body>
</html>
七、函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script type="text/javascript">
// 多行注释shift+alt+a
/*
* 函数:也是一个对象,封装一些功能
* 以字符串形式传递给构造函数
* 代码会在调用时执行
*/
// 以下形式很少用
let fun1 = new Function('console.log(123);');
fun1();
console.log(typeof fun1);
// 一般以下形式声明函数,fun2(形参1, 形参2){}
function fun2(){
console.log(456);
}
fun2();
// 匿名函数声明
let fun3 = function(){
console.log(789);
};
fun3();
/*
* 参数设置
* 调用函数时解析器不会检查实参的类型,要注意是否接收到非法参数
* 调用函数时解析器不会检查实参的数量,多余的没有,少的按undefined
*/
// 求和函数
function sum(a, b){
console.log(a + b);
}
sum(1, 2);
/*
* 函数的返回值,return返回
* return不加值/不写return,返回undefined
* 返回值可以是任意对象
*/
function sum(a, b){
return a + b;
}
let absums = sum(1, 2);
console.log('absums:' + absums);
/*
* 立即执行函数
*/
(function(){
alert('立即执行');
})();
/*
* 全局作用域:
* 1.页面打开时创建,关闭时销毁
* 2.直接编写在script的js代码都是全局作用域
* 3.全局作用域中有一个window对象,创建的全局变量都是window的属性,全局函数都是window的方法
* 4.var变量在所有代码执行前创建,不赋值只声明
* 5.function 函数名(){}声明的函数在所有代码执行前创建
* 函数作用域:
* 1.调用函数时创建,执行完毕后销毁
* 2.函数作用域可以访问全局变量
* 3.访问同名变量采取就近原则
* 4.函数内不使用var声明的变量会被当做全局变量
*/
// 全局作用域
var a = 1;
var b = function(){
console.log('我是window的方法');
};
console.log(window.a);
console.log(window.b);
window.b();
/*
* this指针:this指向函数执行的上下文对象
* this在哪被调用,或者说谁调用this,谁就是this
*/
// 全局调用,this是window,对象调用,this是对象
function fun4(){
console.log(this);
}
fun4();
let obj1 = {
method: fun4
};
obj1.method();
/*
* 工厂方法创建对象
*/
function createobj(name, age){
let obj = {
name: name,
age: age,
sayName: function(){
console.log(this.name);
}
}
obj.sayName();
return obj;
}
let obj2 = createobj('王五', 18);
let obj3 = createobj('程六', 19);
</script>
<title>Document</title>
</head>
<body>
</body>
</html>
八、构造函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
/*
* 构造函数:习惯上首字母大写,其他与普通函数一样
* 构造函数调用使用new
* 调用构造函数时,立刻创建一个新对象,即使构造函数没有return,创建流程:
* 1.立即创建一个新对象
* 2.将新建对象设置为函数中的this
* 3.运行函数中的代码
* 4.将新建对象作为返回值返回
*/
function Person1(name, age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
};
}
let person1 = new Person1('张三', 18);
console.log(person1);
person1.sayName();
// 使用instaneof检查一个对象是否是一个类的实例
console.log(person1 instanceof Person1, person1 instanceof Object);
/*
* 修改构造函数,将方法在全局作用域定义
* 但此方法不好
*/
function fun(){
alert(this.name);
}
function Person2(name, age){
this.name = name;
this.age = age;
this.sayName = fun;
}
let person2 = new Person2('李四', 24);
person2.sayName();
/*
* 每一个函数,解析器都会向函数中添加一个属性prototype
* prototype指向一个原型对象(原型对象还有一个原型),每个函数的原型函数不一样
* 普通函数没有,构造函数有用
* 当以构造函数创建对象时,每个对象都含有一个隐含属性__proto__指向构造函数的原型对象
* 所以可以将对象共有属性添加到原型对象中
* 每次先在实例中找,没有的话去原型找
*/
function Person3(name, age){
this.name = name;
this.age = age;
}
Person3.prototype.sayName = function(){
alert(this.name);
};
let person3 = new Person3('王五', 29);
console.log('sayName' in person3);
person3.sayName();
// 检查实例对象是否有某个属性/方法,用in的话原型有也是true
// 原型对象还有一个原型
console.log(person3.hasOwnProperty('sayName')); // fasle
console.log(person3.__proto__.hasOwnProperty('sayName')); //true
console.log(person3.__proto__.__proto__.hasOwnProperty('hasOwnProperty')); //true
/*
* 输出对象,相当于输出对象.toString()方法的返回值
* 可以重新定义toString方法覆盖原方法,这样打印对象时,就会按照重新定义的方法输出结果
*/
console.log(person3 == (person3.toString())); // true
console.log(person3.__proto__.hasOwnProperty('toString')); // false
console.log(person3.__proto__.__proto__.hasOwnProperty('toString')); // true
console.log(person3); // Person3 {name: '王五', age: 29},这样显示纯因为Chrome,实际就是调用toString方法
console.log(person3.toString()); // [object Object]
person3.__proto__.__proto__.toString = function(){
return '我是重新定义的原型的原型的toString方法';
}
console.log(person3 == (person3.toString())); // true
console.log(person3); // Person3 {name: '王五', age: 29},这样显示纯因为Chrome,实际就是调用toString方法
console.log(person3.toString()); // 我是重新定义的toString方法
</script>
</head>
<body>
</body>
</html>
九、数组、call和apply、arguments
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
/*
* 数组:数字做索引,数组[索引]=值
* 读取不存在的元素,会返回undefined
* 元素可以放任意的数据类型
*/
let arr1 = new Array();
arr1[0] = 10;
arr1[1] = 33;
console.log(arr1.length);
arr1.length = 3;
let arr2 = [1, 2, 3, 4, 5, 6];
let arr3 = new Array(1, 2, 3);
let arr4 = new Array(10); // 创建长度为10的数组
/*
* 四种方法:
* 1.push(),添加元素到末尾,可同时添加多个,返回值是数组新长度
* 2.pop(),删除末尾最后一个元素,返回值是删除的元素
* 3.unshift(),向开头添加一个或多个元素,返回值是数组新长度
* 4.shift(),删除并返回数组第一个元素
*/
/*
* forEach:遍历数组
* 需要一个函数作为参数
* 数组有几个元素,函数执行几次
* 浏览器会将遍历到的元素以实参形式传递进函数中,有三个参数
* 1.当前遍历元素的value
* 2.当前遍历元素的index
* 3.正在遍历的数组,是一个对象Object
*/
arr1.forEach(function(value, index, arr){
console.log(value, index, arr);
});
/*
* slice:切片,方法同python,不会影响原数组
* splice:删除指定元素,可删除多个,会影响原数组
* 1.第一个参数是开始位置
* 2.第二个参数是删除数量
* 3.第三个参数是向删除位置前添加的新元素
*/
/*
* concat:连接两个或多个数组,返回新数组,不影响原数组
* join:数组转字符串,使用括号内的字符拼接,不设置默认使用英文逗号连接,不影响原数组
* reverse:数组转置,影响原数组
* sort:数组排序,默认升序,会影响原数组,可自定义排序规则,函数返回大于0的值元素会交换位置
*/
arr5 = arr1.concat(arr2);
arr6 = arr1.join(':');
arr1.reverse();
arr1.sort(function(a, b){
// 默认a在b前
// 此是降序
return b - a;
});
/*
* call和apply:
* 1.都是函数对象的方法,需要通过函数对象来调用
* 2.函数调用call和apply都会执行函数
* 3.可以在调用call和apply时传入一个对象作为参数,此参数会成为函数执行的this
* 4.第二第三及之后的参数是函数的实参,其中call可以直接传,apply需要将实参封装到数组中传
*/
function fun1(a, b){
alert(this);
}
let obj1 = new Object();
fun1.call(obj1, 1, 2);
fun1.apply(obj1, [1, 2]);
/*
* 在调用函数时,浏览器每次都会传递两个隐含参数:
* 1.函数上下文对象this
* 2.封装实参的对象arguments,是一个类数组对象,不是数组
* 其中argument可以通过索引来获取实参,可以获取长度,不定义形参也可以获取
* arguments.callee可以获取当前执行的函数对象
*/
function fun2(){
// console.log(arguments instanceof Array); // false
console.log(Array.isArray(arguments)); // false
console.log(arguments.length);
console.log(arguments[0]);
console.log(arguments.callee == fun2); // true
}
fun2(1, 2);
</script>
</head>
<body>
</body>
</html>
十、Date、Math
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script type="text/javascript">
/*
* Date对象
*/
// 直接构造函数创建Date对象,封装为当前代码执行时间
let date1 = new Date();
// 传入指定参数得到指定时间
let date2 = new Date('12/03/2016 12:30:10');
/*
* 方法:
* 1.getDate,获取当前日期对象是几号
* 2.getDay,获取当前日期对象是周几,周日是0,范围0-6
* 3.getMonth,获取当前日期对象是几月,范围0-11
* 4.getFullYear,获取年份
* 5.getTime,获取当前日期对象的时间戳,从1970年1月1日到当前日期所花毫秒数
* 6.Date.now(),获取当前代码执行的时间戳
*/
/*
* Math对象:不是构造函数,不用创建对象,其中封装了相关的属性和方法
*
*/
// 常量
console.log(Math.PI, Math.E);
// 方法
console.log(Math.abs(-5)); // 5
console.log(Math.ceil(1.2)); // 2
console.log(Math.floor(2.9)); // 2
console.log(Math.round(1.5)); // 2
console.log(Math.random()); // [0, 1)随机数
console.log(Math.round(Math.random()*(y-x)+x)); // [x, y]随机数
console.log(Math.max(1, 2, 3, 4)); // 最大值,最小值是min
console.log(Math.pow(2, 3)); // 2的3次方
console.log(Math.sqrt(2)); // 2的平方
</script>
</head>
<body>
</body>
</html>
十一、DOM查询
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button id="btn1" onclick="alert('点我干嘛');">我是一个按钮</button>
<div class="box1">
<div>我是box1的div</div>
</div>
<div id="box2">
<div>我是box2的div</div>
</div>
<a href="https://www.baidu.com/">点我不跳转</a>
<input type="text" placeholder="请输入年龄">
<button id="btn2">提交</button>
</body>
<script>
// 文档节点:代表整个页面,即document
console.log(document);
/*
* 顺序不能错,比如先声明button再getElementById,浏览器自上而下实行
* 如果想写上边,可以使用window.onload = function(){JS代码},这样代码会在页面加载后执行
*/
// 通过文档对象获取某个对象,并操作
// 还有getElementsByTagName(获取的是一个数组)、getElementsByName、还有getElementsByTagName(获取的是一个数组)、getElementsByClassName、
let btn1 = document.getElementById('btn1');
btn1.innerHTML = "I'm a button";
/*
* 事件:用户和浏览器之间的交互,比如点按钮、鼠标移动
* 在事件对应的属性中添加一些js代码,当事件发生时代码执行
* 1.耦合写法,比如上边的onclick
* 2.在script标签中写,事件绑定处理函数
*/
// 绑定单击事件
btn1.onclick = function(){
alert('你还点');
};
/*
* childNodes:所有子节点,包括换行
* children:所有子元素
* firstChild:第一个子节点,包括换行
* firstElementChild:第一个子元素
*
* parentNode:父节点
* previousSibling:前一个兄弟节点
* previousElementSibling:前一个兄弟元素
* nextSibling:后一个兄弟节点
*/
// 获取body、html
let body = document.body;
let html = document.documentElement;
// 根据CSS选择器查询元素节点,如果满足条件的很多,只返回第一个,返回全部用all,此时返回的是类数组
let box1div = document.querySelector('.box1 div');
let box2div = document.querySelectorAll('#box2 div');
/*
* 超链接元素的onclick属性的函数返回false会取消超链接的跳转
* this指代所点击的元素
* confirm用于弹出确认框
* 输出框的value可以获得输入的内容
*/
let a1 = document.getElementsByTagName('a')[0];
a1.onclick = function(){
let ifquren = confirm('是否删除?');
if(ifquren)
alert(this);
console.log(this);
return false;
}
let btn2 = document.getElementById('btn2');
btn2.onclick = function(){
let input1 = document.getElementsByTagName('input')[0];
console.log(input1.value);
}
/*
* 通过JS修改元素样式:元素.style.样式名 = '样式值'(只能读内联样式)
* !!!样式名:带-的不能直接用,把名称改为驼峰命名即可,比如background-color改为backgroundColor
*
* 以下均只读
* 获取当前正在显示的样式(不局限于内联,但仅IE8支持):元素.currentStyle.样式名 = '样式值'
* 获取当前正在显示的样式(其他浏览器,IE8不支持):
* 1.getComputedStyle(元素, 伪元素),伪元素一般都是null
* 2.返回值是对象,可以 对象.样式名 获取样式值
*/
</script>
</html>
十二、事件对象
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#areaDiv{
width: 300px;
height: 50px;
border: 1px solid black;
margin-bottom: 10px;
}
#showMsg{
width: 300px;
height: 20px;
border: 1px solid black;
}
#box1{
width: 200px;
height: 200px;
border: 1px solid red;
position: absolute;
}
</style>
</head>
<body>
<div id="areaDiv"></div>
<div id="showMsg"></div>
<div id="box1"></div>
</body>
<script>
// 该事件在鼠标在元素内移动时触发
let areaDiv = document.getElementById('areaDiv');
let showMsg = document.getElementById('showMsg');
areaDiv.onmousemove = function(event){
// 当事件触发时,浏览器每次都会向函数中传递一个事件对象,封装了事件的所有信息
let x = event.clientX; // 获取鼠标横坐标
let y = event.clientY; // 获取鼠标纵坐标
showMsg.innerHTML = 'x=' + x + ',y=' + y;
};
// div随着鼠标移动
let box1 = document.getElementById('box1');
document.onmousemove = function(event){
let left = event.pageX;
let top = event.pageY;
box1.style.left = left + 'px';
box1.style.top = top + 'px';
};
</script>
</html>
十三、事件冒泡、事件委派、事件绑定
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box1{
width: 200px;
height: 200px;
background-color: yellowgreen;
}
#s1{
background-color: yellow;
}
</style>
</head>
<body>
<div id="box1">
我是box1
<span id="s1">我是span</span>
</div>
<button id="btn1">添加超链接</button>
<ul id="u1">
<li><a href="javascript:;" class="link">超链接1</a></li>
<li><a href="javascript:;" class="link">超链接2</a></li>
<li><a href="javascript:;" class="link">超链接3</a></li>
</ul>
<button id="btn2">事件绑定</button>
</body>
<script>
/*
* 事件冒泡:事件向上传到,点span触发,div和body也触发
*/
let s1 = document.getElementById('s1');
s1.onclick = function(event){
alert('span触发');
// 取消冒泡
event.cancelBubble = true;
};
let box1 = document.getElementById('box1');
box1.onclick = function(){
alert('div触发');
};
// document.body.onclick = function(){
// alert('body触发');
// };
/*
* 事件委派:只绑定一次事件,后边新加的事件不需要重新设置(因为for循环会在页面构建时先执行)
* 可以将事件绑定给其父元素(共同的祖先元素),后代触发时,会冒泡到祖先一样触发
*/
let btn1 = document.getElementById('btn1');
let u1 = document.getElementById('u1');
u1.onclick = function(event){
// 用target获得触发事件的对象,设置仅点击超链接会alert,点击u1其他地方不触发
// if(event.target.className == 'link')
// alert('u1的触发事件');
// 使用className判断是有隐患的,万一某个a的class改名了,下面方法更严谨
if(event.target.tagName == 'A')
alert('u1的触发事件');
};
btn1.onclick = function(){
let newli = document.createElement('li');
// 不能用u1.length,因为对象没有length属性,只有String和Array有
newli.innerHTML = '<a href="javascript:;" class="link">超链接' + (u1.getElementsByTagName('li').length + 1) + '</a>';
u1.appendChild(newli);
};
/*
* 使用对象.事件 = 函数绑定,只能绑定一个,后会覆盖前
* 事件绑定:addEventListener,参数为
* 1.事件的字符串,不要on,只click
* 2.回调函数,当事件触发时该函数会被调用
* 3.是否在捕获阶段触发事件,一般为false,会true时触发顺序和冒泡相反
*/
// 同时绑定多个,先后执行
let btn2 = document.getElementById('btn2');
btn2.addEventListener('click', function(){
alert(1);
}, false);
btn2.addEventListener('click', function(){
alert(2);
}, false);
</script>
</html>
十四、拖拽实现
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
#box1{
width: 100px;
height: 100px;
background-color: red;
position: absolute;
}
</style>
</head>
<body>
<div id="box1"></div>
</body>
<script>
/*
* 拖拽:
* 1.鼠标按下,开始拖拽
* 2.鼠标移动,元素跟着移动
* 3.鼠标松开,停止拖拽
*/
let box1 = document.getElementById('box1');
box1.onmousedown = function(event){
let l = event.clientX;
let t = event.clientY;
let left_diff = l - box1.offsetLeft;
let top_diff = t - box1.offsetTop;
document.onmousemove = function(event){
let left = event.clientX;
let top = event.clientY;
box1.style.left = left - left_diff + 'px';
box1.style.top = top - top_diff + 'px';
};
document.onmouseup = function(){
document.onmousemove = false;
// 取消自己,不然点击空白松开还会触发alert
document.onmouseup = false;
alert(1);
};
};
</script>
</html>
十五、JSON
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
</body>
<script>
/*
* JSON:特殊格式的字符串,属性名必须双引号
* JSON分类:JSON对象(用{})、JSON数组(用[])
* JSON中允许的值:字符串、数值、布尔、null、普通对象(Object)、数组
*
*/
// JSON举例
let json1 = '{"name": "孙悟空", "age": 18, "gender": "男"}';
let json2 = '[1, 3, 5, "你好"]';
let json3 = '{"arr": [1, 2, 3]}';
// JSON转js对象
let obj1 = JSON.parse(json1);
console.log(obj1);
// js对象转JSON
let json4 = JSON.stringify(obj1);
console.log(json4);
</script>
</html>