1. Javascript简介
web前端有三层:
-
HTML:从语义的角度,描述页面的结构
-
CSS:从审美的角度,描述样式(美化页面)
-
JavaScript:从交互的角度,描述行为(提升用户体验)
2. 历史背景介绍
布兰登 艾奇 1995年在网景公司 发明的JavaScript
一开始的JavaScrip叫LiveScript
同一个时期 比如 VBScript,JScript等,但是后来被JavaScript打败了,现在的浏览器只运行一种脚本语言叫JavaScript
3. JavaScript的发展
2003年之前,JavaScript被认为“牛皮鲜”,用来制作页面上的广告,弹窗、漂浮的广告。什么东西让人烦,什么东西就是JavaScript开发的。所以浏览器就推出了屏蔽广告功能。
2004年,JavaScript命运开始改变,那一年,谷歌公司开始带头使用Ajax技术,Ajax技术就是JavaScript的一个应用。并且,那时候人们逐渐开始提升用户体验了。Ajax有一些应用场景。比如,当我们在百度搜索框搜文字时,输入框下方的智能提示,可以通过Ajax实现。比如,当我们注册网易邮箱时,能够及时发现用户名是否被占用,而不用调到另外一个页面。
2007年乔布斯发布了第一款iPhone,这一年开始,用户就多了上网的途径,就是用移动设备上网。JavaScript在移动页面中,也是不可或缺的。并且这一年,互联网开始标准化,按照W3C规则三层分离,JavaScript越来越被重视。
2010年,人们更加了解HTML5技术,HTML5推出了一个东西叫做Canvas(画布),工程师可以在Canvas上进行游戏制作,利用的就是JavaScript。
2011年,Node.js诞生,使JavaScript能够开发服务器程序了。
React-native inoic
如今,WebApp已经非常流行,就是用网页技术开发手机应用。手机系统有iOS、安卓。比如公司要开发一个“携程网”App,就需要招聘三队人马,比如iOS工程师10人,安卓工程师10人,前端工程师10人。共30人,开发成本大;而且如果要改版,要改3个版本。现在,假设公司都用web技术,用html+css+javascript技术就可以开发App。也易于迭代(网页一改变,所有的终端都变了)。
虽然目前WebApp在功能和性能上的体验远不如Native App,但是“WebApp慢慢取代Native App”很有可能是未来的趋势。
3. JavaScript的组成
-
ECMAScript 5.0:定义了js的语法标准: 包含变量 、表达式、运算符、函数、if语句 for循环 while循环、内置的函数
-
DOM :操作网页上元素的API。比如让盒子显示隐藏、变色、动画 form表单验证
-
BOM:操作浏览器部分功能的API。比如刷新页面、前进后退、让浏览器自动滚动
二、ECMAScript5.0基础语法
1. JS的引入方式
-
内接式
<!--可以在任意地方使用,建议在body之后写 --> <script type="text/javascript"></script>
<!--相当于引入了某个模块--> <script type="text/javascript" src = './index.js'></script>
2. 变量的使用
-
定义变量:var就是一个关键字,用来定义变量。所谓关键字,就是有特殊功能的小词语。关键字后面一定要有空格隔开。
-
变量的赋值:等号表示赋值,将等号右边的值,赋给左边的变量。
-
变量名:我们可以给变量任意的取名字。
变量要先定义,才能使用。
3. 基本数据类型
数值类型:number
在JavaScript中,只要是数,就是数值型(number)的。无论整浮、浮点数(即小数)、无论大小、无论正负,都是number类型的。
var c = 10 + ''; // 数值转换成字符串 consoloe.log(typeof c); // string
字符串类型:string
连字符和+号的区别
键盘上的+
可能是连字符,也可能是数字的加号。
总结:如果加号两边都是数值,此时是加。否则,就是连字符(用来连接字符串)。
var isShow = 1 > 1; cconsole.log(typeof isShow); // boolean
var d = null; // 空对象 object console.log(typeof d); // object
未定义:undefined
var d1 console.log(d1); // 值是undefined console.log(typeof d1); // unfefined 数据类型 颜色比上面的深
浮躁的数据类型
Python | |
---|---|
Function | def |
Object | dict |
Array | List |
String | string |
Date | time模块 |
大部分和python一样。
和Python不一样的:
var x = 5; var y = '5'; // == 比较的是值的相等 console.log(x==y); // true // === 等同于,比较的是值和数据类型(内存地址) console.log(x===y); // false // != 不等于 // !== 不等同于 // 自增 自减 var a = 5; // 先将a的值赋值给b输出,然后再对a++,a此时是6 var b = a++; console.log(a); // 6 console.log(b); // 5 var a = 5; // 先a++并将a直接输出,在将输出的值赋值给b var b = ++a; console.log(a); // 6 console.log(b); // 6
5. 数据类型的转换
将number类型转换成string类型
// 1. 隐式抓换 var n1 = 123; var n2 = '123'; console.log(n1 + n2); // 默认转换成字符串类型 // 2. 强制转换 // String()toString() var str1 = String(n1); console.log(typeof str1); // string var num = 2334; var numStr = num.toString(); console.log(typeof numStr); // number
// Number // 情形一 var stringNum = '131313'; var num = Number(stringNum); console.log(num) // 131313 console.log(typeof num); // number // 情形二 var stringNum2 = '13.1313asdasda'; var num2 = Number(stringNum2); console.log(num) // NaN Not a Number 不是nunber,但是还是number类型 console.log(typeof num2); // number // parseInt()和parseFloat()可以解析一个字符串 并且返回一个整数和浮点型 console.log(parseInt(stringNum2)); // 13 只保留整数 console.log(parseFloat(stringNum2)); // 13.1313
var age = 20; if(age > 18){ // {}作为当前的作用域 console.log('可以考驾照'); // 可以考驾照 } console.log(2222); // 照样执行
var age = 16; if(age > 18){ // {}作为当前的作用域 console.log('可以考驾照'); }else{ console.log('回家呆着去'); // 回家呆着去 } console.log(2222); // 照样执行
var age = 18; if(age==18){ //{}相当于作用域 console.log('可以去会所'); }else if(age==30){ console.log('该娶媳妇了!!'); }else{ console.log('随便你了') } alert(2222); //下面的代码照样执行
//1.模拟 如果总分 >400 并且数学成绩 >89分 被清华大学录入 //逻辑与&& 两个条件都成立的时候 才成立 var sum = 300; var math = 89; if(sum>400 && math>90){ console.log('清华大学录入成功') }else{ alert('高考失利') }
//2.模拟 如果总分>400 或者你英语大于85 被复旦大学录入 //逻辑或 只有有一个条件成立的时候 才成立 var sum = 498; var english = 90; if(sum>500 || english>85){ alert('被复旦大学录入') }else{ alert('高考又失利了') }
switch 语句
var gameScore = 'good'; switch(gameScore){ //case表示一个条件 满足这个条件就会走进来 遇到break跳出。break终止循环。如果某个条件中不写 break,那么直到该程序遇到下一个break停止 case 'good': console.log('玩的很好'); //break表示退出 break; // 如果不写break,那么程序不会停止直到遇到下一个break,这个叫case穿透。 case 'better': console.log('玩的老牛逼了'); break; case 'best': console.log('恭喜你 吃鸡成功'); break; default: // 不满足所有条件就执行这个 console.log('很遗憾') ; break; } //注意:switch相当于if语句 但是玩switch的小心case穿透
while循环
任何语言的循环离不开这三步:
-
初始化循环变量
-
判断循环条件
-
更新循环变量
// 例子:打印 1~9之间的数 var i = 1; //初始化循环变量 while(i<=10){ //判断循环条件 console.log(i); // i++ i += 1; //更新循环条件 }
do-while
用途不大:就是先做一次 ,上来再循环
//不管有没有满足while中的条件do里面的代码都会走一次 var i = 3;//初始化循环变量 do{ console.log(i) i++;//更新循环条件 }while (i<2) //判断循环条件 // 3
for循环
for循环遍历列表是最常用的对数据的操作
//输出1~10之间的数 for(var i=1; i<=10; i++){ console.log(i) } //课堂练习:输入1~100之间所有数之和 var sum = 0; for(var i = 1;i<=100;i++){ sum += i } console.log(sum);
// 往文档上写内容 // document.write('*'); for(var i=0; i<3; i++){ for(var j=1; j<=6; j++){ document.write('*'); } document.write('<br>'); } // 在浏览器中输出直角三角形 for(var i=1; i<10; i++){ for(var j=1; j<=i; j++){ document.write('*'); } document.write('<br>'); } // 在浏览器中输出 等腰三角形 for(var i=1;i<=6;i++){ //控制行数,一共显示6行 记得换行document.write('<br>'); //控制我们的空格数 for(var s=i;s<6;s++){ document.write(' '); } //控制每行的输出*数 for(var j=1;j<=2*i-1;j++){ document.write('*'); } document.write('<br>'); }
7. 常用内置对象(复杂数据类型)
数组Array(python里的列表)
1.字面量方式创建
var colors = ['red','green','yellow'];
所有的变量都挂载到了全局对象window
2.使用构造函数
var colors = new Array(); console.log(colors); // length:0 __proto__:Array(0) 数组的父类 colors[0] = 'red'; colors[1] = 'green'; colors[2] = 'yello'; // for循环遍历 for(var i=0; i<colors.length;i++){ console.log(i,colors[i]); }
数组的常用方法
数组的合并 concat()
var north = ['北京','山东','天津']; var south = ['东莞','深圳','上海']; var newCity = north.concat(south); console.log(newCity);
join() 将数组中元素使用指定的字符串连接起来,它会形成一个新的字符串
var score = [98,78,76,100,0]; var str = score.join('|'); console.log(str);//"98|78|76|100|0"
slice(start,end); 返回数组的一段记录,顾头不顾尾
var arr = ['张三','李四','王文','赵六']; var newArr = arr.slice(1,3); console.log(newArr);//["李四", "王文"]
push() 向数组最后添加一个元素
var arr = ['张三','李四','王文','赵六']; arr.push('小马哥'); console.log(arr);//["张三", "李四","王文","赵六","小马哥"]
pop 移除数组的最后一个元素
var arr = ['张三','李四','王文','赵六']; arr.pop(); console.log(arr);//["张三", "李四","王文"]
reverse() 翻转数组
var names = ['alex','xiaoma','tanhuang','angle']; //4.反转数组 names.reverse(); console.log(names);
sort对数组排序
var names = ['alex','xiaoma','tanhuang','abngel']; names.sort(); console.log(names);// ["alex", "angle", "tanhuang", "xiaoma"]
判断是否为数组:isArray()
布尔类型值 = Array.isArray(被检测的值) ;
forEach(fn) == 回调函数、匿名函数。通过forEach遍历数组的每一项内容。
var names = ['alex','xiaoma','tanhuang','abngel']; names.forEach(function(item,index){ console.log(item); // 内容 console.log(index); // 索引 })
字符串的常用方法
chartAt() 返回指定索引的位置的字符
var str = 'alex'; var charset = str.charAt(1); console.log(charset);//l
concat 返回字符串值,表示两个或多个字符串的拼接
var str1 = 'al'; var str2 = 'ex'; console.log(str1.concat(str2,str2));//alexex
replace(a,b) 将字符串a替换成字符串b
var a = '1234567755'; var newStr = a.replace("4567","****"); console.log(newStr);//123****755
indexof() 查找字符的下标,如果找到返回字符串的下标,找不到则返回-1 。跟seach()方法用法一样
var str = 'alex'; console.log(str.indexOf('e'));//2 console.log(str.indexOf('p'));//-1
slice(start,end) 左闭右开 分割字符串
var str = '小马哥'; console.log(str.slice(1,2));//马
split('a',1) 以字符串a分割字符串,并返回新的数组。如果第二个参数没写,表示返回整个数组,如果定义了个数,则返回相应的个数。
var str = '我的天呢,a是嘛,你在说什么呢?a哈哈哈'; console.log(str.split('a'));//["我的天呢,", "是嘛,你在说什么呢?", "哈哈哈"]
substr(statr,end) 左闭右开
var str = '我的天呢,a是嘛,你在说什么呢?a哈哈哈'; console.log(str.substr(0,4));//我的天呢
toLowerCase()转小写
var str = 'XIAOMAGE'; console.log(str.toLowerCase());//xiaomage
toUpperCase()转大写
var str = 'xiaomage'; console.log(str.toUpperCase());//XIAOMAGE
特别:
//将number类型转换成字符串类型 var num = 132.32522; var numStr = num.toString(); console.log(typeof numStr); // string //四舍五入 var newNum = num.toFixed(2) console.log(newNum); // 132.33 // 清除空格 var str10 = ' edward '; console.log(str10.trim());
var x = 1.234; //天花板函数 表示大于等于x,并且与它最接近的整数是2 var a = Math.ceil(x); console.log(a);//2 // 分页的时候用 var pageNum = 12345 / 30; console.log(Math.ceil(pageNum)); // 411.5 --> 412
Math.floor 向下取整,'地板函数'
var x = 1.234; // 小于等于 x,并且与它最接近的整数 1 var b = Math.floor(x); console.log(b);//1
求两个数的最大值和最小值
//求 两个数的最大值 最小值 console.log(Math.max(2,5));//5 console.log(Math.min(2,5));//2
随机数 Math.random() --> 最重要
var ran = Math.random(); console.log(ran); // [0,1) // 200 ~ 500 求min~max之间的随机数 min + Math.random()*(max-min) console.log(200 + Math.random() * (300));
8. 函数
函数:就是把将一些语句进行封装,然后通过调用的形式,执行这些语句。
函数的作用:
-
解决大量的重复性的语句
-
简化编程,让编程模块化
普通函数
# python 中声明函数 def add(x,y): return x+y # 调用函数 print(add(1,2))
//js中声明函数 function add(x,y){ return x+y; } //js中调用函数 console.log(add(1,2));
var add = function(x,y){ return x + y; }; console.log(typeof add); // function console.log(add(1,2));
9. JavaScript的面向对象
Javascript中创建对象的方式和很多语言不同。
使用Object或对象字面量创建对象
var student = new Object(); student.name = "easy"; student.age = "20"; console.log(student); // {name: "easy", age: "20"} // 如果你嫌这种方法有一种封装性不良的感觉。来一个对象字面量方式创建对象。 (推荐) var student2 = { name: "alex", age: 26, fav: function () { // this指的是当前对象,和python中的self类似 console.log(this.name); } }; console.log(student2);
当我们要创建同类的student1,student2,…,studentn时,我们不得不将以上的代码重复n次....
能不能像工厂车间那样,有一个车床就不断生产出对象呢?我们看”工厂模式”。
工厂模式创建对象
JS中没有类的概念,那么我们不妨就使用一种函数将以上对象创建过程封装起来以便于重复调用,同时可以给出特定接口来初始化对象
function createStudent(name, age) { var obj = new Object(); obj.name = name; obj.age = age; return obj; } var student1 = createStudent("easy1", 20); var student2 = createStudent("easy2", 20); ... var studentn = createStudent("easyn", 20); // 我们同时又定义了”生产”水果对象的createFruit()函数: function createFruit(name, color) { var obj = new Object(); obj.name = name; obj.color = color; return obj; } var v1 = createStudent("easy1", 20); var v2 = createFruit("apple", "green"); console.log(v1 instanceof Object); // true console.log(v2 instanceof Object); // true
我们用instanceof操作符去检测,他们统统都是Object类型。我们的当然不满足于此,我们希望v1是Student类型的,而v2是Fruit类型的。为了实现这个目标,我们可以用自定义构造函数的方法来创建对象。这就引出构造函数模式创建对象
构造函数模式创建对象
在进行自定义构造函数创建对象之前,我们首先了解一下构造函数
和普通函数
有什么区别。
1、实际上并不存在创建构造函数的特殊语法,其与普通函数唯一的区别在于调用方法。对于任意函数,使用new操作符调用,那么它就是构造函数;不使用new操作符调用,那么它就是普通函数。
2、按照惯例,我们约定构造函数名以大写字母开头,普通函数以小写字母开头,这样有利于显性区分二者。例如上面的new Array(),new Object()。
3、使用new操作符调用构造函数时,会经历(1)创建一个新对象;(2)将构造函数作用域赋给新对象(使this指向该新对象);(3)执行构造函数代码;(4)返回新对象;4个阶段。
我们使用构造函数将工厂模式
的函数重写,并添加一个方法属性:
function Student(name, age) { this.name = name; this.age = age; this.alertName = function(){ alert(this.name) }; } function Fruit(name, color) { this.name = name; this.color = color; this.alertName = function(){ alert(this.name) }; } var v1 = new Student("easy", 20); var v2 = new Fruit("apple", "green"); alert(v1 instanceof Student); //true alert(v2 instanceof Student); //false alert(v1 instanceof Fruit); //false alert(v2 instanceof Fruit); //true alert(v1 instanceof Object); //true 任何对象均继承自Object alert(v2 instanceof Object); //true 任何对象均继承自Object
我们会发现Student和Fruit对象中共有同样的方法,当我们进行调用的时候这无疑是内存的消耗。
function Student(name, age) { this.name = name; this.age = age; this.alertName = alertName; } function alertName() { alert(this.name); } var stu1 = new Student("easy1", 20); var stu2 = new Student("easy2", 20);
在调用stu1.alertName()时,this对象才被绑定到stu1上。
我们通过将alertName()函数定义为全局函数,这样对象中的alertName属性则被设置为指向该全局函数的指针。由此stu1和stu2共享了该全局函数,解决了内存浪费的问题
但是,通过全局函数的方式解决对象内部共享的问题,终究不像一个好的解决方法。如果这样定义的全局函数多了,我们想要将自定义对象封装的初衷便几乎无法实现了。更好的方案是通过原型对象模式来解决。
原型模式创建对象
我们主要使用这种方法创建对象
// prototype 它是当前对象的父类 function Student() { this.name = 'easy'; this.age = 20; } Student.prototype.alertName = function(){ // 继承 alert(this.name); }; var stu1 = new Student(); var stu2 = new Student(); stu1.alertName(); //easy 继承 stu2.alertName(); //easy console.log(stu1==stu2); //false 比较的是内存地址和值 alert(stu1.alertName == stu2.alertName); //true 二者共享同一函数
10. 伪数组arguments
arguments代表的是实参。有个讲究的地方是:arguments只在函数中使用。
fn(2,4); fn(2,4,6); fn(2,4,6,8); function fn(a,b,c) { console.log(arguments); // 参数 console.log(fn.length); //获取形参的个数 console.log(arguments.length); //获取实参的个数 console.log("----------------"); }
fn(2,4); fn(2,4,6); fn(2,4,6,8); function fn(a,b) { arguments[0] = 99; //将实参的第一个数改为99 arguments.push(8); //此方法不通过,因为无法增加元素 } // 可以被for循环 for(var i=0; i<arguments.length; i++){ console.log(arguments[i]); }
清空数组的几种方式:
var array = [1,2,3,4,5,6]; array.splice(0); //方式1:删除数组中所有项目 array.length = 0; //方式2:length属性可以赋值,在其它语言中length是只读 array = []; //方式3:推荐
11. Date
创建日期对象只有构造函数一种方式,使用new关键字
var myDate = new Date(); console.log(myDate); // Wed Jan 16 2019 16:48:38 GMT+0800 (China Standard Time) // 获取本地时间,月份中的第几天(1~31) console.log(myDate.getDate()); // getMonth() 获取指定日期对象月份(0~11) console.log(myDate.getMonth()+1); // 得出的值加1才是当前月份 // getFullYear() 返回四位数的年份 console.log(myDate.getFullYear()); // getDay() 返回星期(0~6),0代指星期天 console.log(myDate.getDay()); // getMinutes() getSeconds() console.log(myDate.getMinutes()); console.log(myDate.getSeconds()); //返回本地时间 console.log(myDate.toLocaleString()); // 1/16/2019, 4:51:06 PM
12. JSON
概念简介
JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,采用完全独立于语言的文本格式,是理想的数据交换格式。同时,JSON是 JavaScript 原生格式,这意味着在 JavaScript 中处理 JSON数据不须要任何特殊的 API 或工具包。
在JSON中,有两种结构:对象和数组。
对象
var packJSON= {"name":"alex", "password":"123"};console.log(packJSON); // {name: "alex", password: "123"}
// 数组是值的有序集合 var packJSON = [{"name":"alex", "password":"123"}, {"name":"wusir", "password":"456"}]; console.log(packJSON); // 0: {name: "alex", password: "123"} // 1: {name: "wusir", password: "456"}
JSON对象和JSON字符串转换
在数据传输过程中,JSON是以字符串的形式传递的,而JS操作的是JSON对象,所以,JSON对象和JSON字符串之间的相互转换是关键。
JSON字符串转换JSON对象(重要)
// JSON字符串 var jsonStr ='{"name":"alex", "password":"123"}' ; var jsonobject = JSON.parse(jsonStr); console.log(jsonobject); // {name: "alex", password: "123"}
// JSON对象 var jsonObject = {"name":"alex", "password":"123"}; var jsonstr =JSON.stringify(jsonObject); console.log(jsonstr); // {"name":"alex","password":"123"}
遍历JSON对象和JSON数组
遍历JSON对象
var packJSON = {"name":"alex", "password":"123"} ; for(var k in packJSON ){//遍历packJSON 对象的每个key/value对,k为key console.log(k + ' ' + packJSON[k]); // name alex // password 123 }
var packJSON = [{"name":"alex", "password":"123"}, {"name":"wusir", "password":"456"}]; for(var i in packJSON){//遍历packJSON 数组时,i为索引 console.log(packJSON[i].name + " " + packJSON[i].password); // alex 123 // wusir 456 }
// 1. 构造函数创建 var str = 'luffy 2019'; var reg = new RegExp('i','ig'); // i:不区分大小写。 g:全局匹配 // 2. 字面量方式创建 var reg1 = /y/ig; // 找 y // ------ 正则对象提供的检索方式 ------- // test() 检测是否包含定义字符模式,返回布尔 // console.log(reg1.test(str)); // true // exec() 用来检索字符串中正则表达式的匹配。匹配到了返回存放结果的数组,匹配不到返回null console.log(reg1.lastIndex); //0 console.log(reg1.exec(str)); //["y", index: 4, input: "luffy 2019", groups: undefined] console.log(reg1.lastIndex); // 5 // 3. ------ 常用方法 ------ var str2 = 'hello world'; var reg2 = /o/g; // match 使用正则表达式对字符串进行查找,并将包含查找的结果作为数组返回 console.log(str2.match(reg2)); // ["o", "o"] // replace() str.replace(替换,被替换的) // console.log(str2.replace(reg2,'*')); // hell* w*rld // search() 显示下标 console.log(str2.search(reg2)); // 4 // split 以匹配的规则分割 console.log(str2.split(reg2)); // ["hell", " w", "rld"]
三、DOM
1. DOM基础
概念
所谓DOM,全称 Docuemnt Object Model 文档对象模型,毫无疑问,此时要操作对象,什么对象?文档对象
在文档中一切皆对象,比如html,body,div,p等等都看做对象,那么我们如何来点击某个盒子让它变色呢?
DOM 为文档提供了结构化表示,并定义了如何通过脚本来访问文档结构。目的其实就是为了能让js操作html元素而制定的一个规范。
解析过程
HTML加载完毕,渲染引擎会在内存中把HTML文档,生成一个DOM树,getElementById是获取内中DOM上的元素节点。然后操作的时候修改的是该元素的属性。
DOM树(一切皆是节点)
-
元素节点:HMTL标签。
-
文本节点:标签中的文字(比如标签之间的空格、换行)
-
属性节点::标签的属性
整个html文档就是一个文档节点。所有的节点都是Object。
DOM可以做什么
-
找对象(元素节点) (获取DOM)
-
设置标签的属性值 (对于标签属性的操作)
-
设置标签的样式 (对于样式属性的操作)
-
设置标签值的操作
-
动态创建和删除元素 (对于DOM的增删改建)
-
事件的触发响应:事件源、事件、事件的驱动程序 (js事件,集合ECMAScript相关知识点对DOM进行操作)
DOM标签结构获取
-
获取文档对象:document
-
获取html:document.documentElement
-
获取body: document.body
获取body中元素节点的三种方式
<div id='box' class='box'></div> <div id='box2' class='box'></div> //方式一:通过id获取单个标签 var oDiv1 = document.getElementById("box"); console.log(oDiv1); // <div id="box" class="box"></div> //方式二:通过标签获得标签数组,所以有s。 var oDiv2 = document.getElementsByTagName("div")[0]; //获取的伪数组,不能使用数组的方法 console.log(oDiv2); // <div id="box" class="box"></div> //方式三:通过类名获得标签数组,所以有s。 var oDiv3 = document.getElementsByClassName("box")[0]; //获取的伪数组,不能使用数组的方法 console.log(oDiv3); // <div id="box" class="box"></div>
2. 事件驱动
绑定事件的方式
JavaScript入口函数 window.onload()
此函数调用,是当页面加载完毕(文档和图片)的时候,触发onload()函数,文档先加载,图片资源后加载
<script type="text/javascript"> window.onload = function () { console.log("alex"); //等页面加载完毕时,打印字符串 } </script>
window.onload()方法存在的问题 (一般不用这个,有别的替代方案)
-
图片加载完成才调用onload方法,大家想个问题,如果现在用户访问JD商城页面,如果JD商城中的脚本文件在window.onload()方法调用,如果此时用户网速卡了,然后图片资源加载失败了,此时用户是做不了任何操作的,所以winodw.onload()方法有很大问题。
-
window.onload()方法 如果脚本中书写两个这样的方法,那么会有事件覆盖现象。
样式属性操作
要操作文档对象了,要遵循事件三步走
-
获取事件源
-
事件
-
事件驱动程序
<div class='box'></div> <style> .box{ 200px; height:200px; background-color:red; } </style> <script> //1.获取事件源(事件对象,在文档中一切的标签都是对象) var oDiv = document.getElementsByClassName('box')[0]; //2.事件 后执行的操作 异步的操作 oDiv.onclick = function(){ //3.事件驱动程序 ps:所有的style中使用的像margin-left,在js操作时都是用marginLeft属性进行赋值 // 点语法 get set // 获取值get console.log(oDiv.style.backgroundColor); // 设置值set oDiv.style.backgroundColor = 'yellow'; //获取的是行内样式的style,把内接式的覆盖掉了 oDiv.style.width = '300px'; }; // 补充:oDiv.onclick=fn()。fn()的是函数的返回值,fn获取的是函数。 </script>
<input type="text" name="user" value="123" id="oinput"> <button id="btn">设置值</button> <div id='box'>wusir</div> <script> window.onload = function () { //函数 解决了冗余性代码(僵尸代码) /* let oBtn = document.getElementById('btn'); let oDiv = document.getElementById('box'); let oInput = document.getElementById('oinput'); */ function $(id){ return document.getElementById(id); } $('btn').onclick = function () { // 对标签文本内容的设置,只获取文本 $('box').innerText = 'alex'; //将标签和文本内容一起解 $('box').innerHTML = '<h1>alex</h1>'; // 表单控件中有value属性的,必须通过value属性来设置值 $('oinput').value = '哈哈哈'; } } </script>
<style> a { display: inline-block; } </style> <body> <!-- 让超链接去执行一个js函数,而不是去跳转到一个地址, 而void(0)表示一个空的方法,也就是不执行js函数。javascript:是伪协议,表示url的内容通过javascript执行。void(0)表示不作任何操作,这样会防止链接跳转到其他页面。这么做往往是为了保留链接的样式,但不让链接执行实际操作。 --> <a href="javascript:void(0);"> <img src="./images/2.png" alt="上一张" id="prev"> </a> <script> window.onload = function () { // 1. 获取事件源 let oImg = document.getElementById('prev'); // 2.事件 oImg.onmouseover = function () { console.log(this); // 好比python中self,谁调用的事件,this指的就是谁 console.log(this.getAttribute('src')); // 获取的相对路径 console.log(this.getAttribute('id')); console.log(this.getAttribute('alt')); // 上面的简写 获取的绝对路径 console.log(this.src); console.log(this.id); console.log(this.alt); // 属性的设置 // this.setAttribute('src','./images/1.png'); this.src = './images/1.png'; }; oImg.onmouseout = function () { // this.setAttribute('src','./images/2.png'); this.src = './images/2.png'; }; }; </script>
<style> #box{ 100px; height:200px; background-color: red; } .active{ display:none; } </style> <body> <button id="btn">隐藏</button> <div id="box" class="box"></div> <script> window.onload = function () { function $(id) { return document.getElementById(id); } /* 通过控制样式属性显示隐藏 var isShow = true; $('btn').onclick = function () { if (isShow){ $('box').style.display = 'none'; isShow = false; this.innerText = '显示'; }else{ $('box').style.display = 'block'; isShow = true; this.innerText = '隐藏'; } } */ // class 如果网页中有频繁性的切换,建议使用这一种 var isShow = true; $('btn').onclick = function () { if(isShow) { // 在js中设置类得通过className $('box').className += ' active'; this.innerText = '显示'; isShow = false; }else{ $('box').className = 'box'; this.innerText = '隐藏'; isShow = true; } } } </script> </body>
DOM的节点操作
createElement、insertBefore、removeChild
<button id="create">创建</button> <button id="remove">移除</button> <div id="box"> <!--<h2>alex</h2>--> <h3 id="haha">哈哈哈 </h3> </div> <script> window.onload = function () { function $(id) { return document.getElementById(id); } var oP = null; $('create').onclick = function () { // 创建p节点元素 oP = document.createElement('h2'); // 设置文本内容 oP.innerText = 'alex'; // 追加元素 父子 父.appendChild(子) // $('box').appendChild(oP); // 兄弟之间插入节点 父元素.insertBefore(新的子节点,作为参考的节点) $('box').insertBefore(oP,$('haha')); // 没有after这种方法 }; /* 创建 ==> 销毁,这样对页面性能是由损耗的,如果页面中频繁出现这种操作就不要使用这种方式了。 如果频繁操性操作,要通过上面那种控制类的样式。注册、登陆可以使用这种方式。 */ $('remove').onclick = function () { // 父.removeChild(子节点) $('box').removeChild(oP); } } </script>
<div id="box"> <button id="btn"> <span>haha</span> </button> </div> <script> window.onload = function () { function $(id) { return document.getElementById(id); } // 获取父节点 亲爹 // console.log($('btn').parentNode); console.log($('btn').parentNode.parentNode.parentNode); // 获取子节点 复数 亲儿子 console.log($('btn').childNodes); $('btn').onclick = function(){ this.parentNode.removeChild(this); } // 自己删除自己 } </script>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> * { padding: 0; margin: 0; } html, body { 100%; height: 100%; } #bg { position: relative; top: 0; left: 0; 100%; height: 100%; background-color: rgba(0, 0, 0, .3); } #login { 300px; height: 300px; border-radius: 3px; background-color: #fff; line-height: 300px; text-align: center; margin: 0 auto; position: relative; } #close { position: absolute; right: 0; top: 0; 20px; height: 20px; background-color: red; line-height: 20px; text-align: center; color: green; cursor: pointer; } </style> </head> <body> <!--打开网页时有一个普通的按钮,点击当前按钮显示一个背景图,中心并弹出一个弹出框,点击X的时候会关闭当前的模态框--> <button id="btn">弹出</button> <script> function $(id) { return document.getElementById(id); } // 1.点击登录按钮 // 北京 let oBg = document.createElement('div'); // 登录框 let oLogin = document.createElement('p'); // 关闭按钮 let oClose = document.createElement('span'); oBg.id = 'bg'; oLogin.id = 'login'; oClose.id = 'close'; oClose.innerText = 'X'; oLogin.innerHTML = '登录框成功弹出'; // 追加 oBg.appendChild(oLogin); oLogin.appendChild(oClose); $('btn').onclick = function () { this.parentNode.appendChild(oBg); this.style.display = 'none'; }; oClose.onclick = function () { oBg.parentNode.removeChild(oBg); $('btn').style.display = 'inline-block'; } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> button { margin: 10px; 100px; height: 40px; cursor: pointer; } button.active { background-color: green; } </style> </head> <body> <button>按钮1</button> <button>按钮2</button> <button>按钮3</button> <button>按钮4</button> <button>按钮5</button> <script> // 需求:鼠标悬浮的button变成绿色(添加类active) let oBtns = document.getElementsByTagName('button'); for (let i = 0; i < oBtns.length; i++) { oBtns[i].onmouseover = function () { // 重要的思想:排他思想:先把所有按钮的className属性置空,然后把当前这个按钮的className设置为active for (var j = 0; j < oBtns.length; j++) { oBtns[j].className = ''; } this.className = 'active'; } } for (let i = 0; i < oBtns.length; i++) { oBtns[i].onmouseout = function () { this.className = ''; } } </script> </body> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> * { margin: 0; padding: 0; } ul { list-style: none; } #tab { 480px; margin: 20px auto; border: 1px solid red; } ul { 100%; overflow: hidden; } #tab ul li { float: left; 160px; height: 60px; line-height: 60px; text-align: center; background-color: #cccccc; } #tab ul li a { color: black; display: block; 100%; height: 100%; text-decoration: none; } #tab ul li.active { background-color: red; } #tab p { display: none; height: 200px; text-align: center; line-height: 200px; background-color: red; } #tab p.active { display: block; } </style> </head> <body> <div id="tab"> <ul> <li class="active"> <a href="javascript:void(0);">首页</a> </li> <li> <a href="javascript:void(0);">新闻</a> </li> <li> <a href="javascript:void(0);">图片</a> </li> </ul> <p class="active">首页内容</p> <p>新闻内容</p> <p>图片内容</p> </div> <script> // //需求:鼠标放到上面的li上,li本身变色(添加类),对应的p也显示出来(添加类); //思路:1.点亮上面的盒子。 2.利用索引值显示下面的盒子。 /* 变量提升 console.log(a); var a = 10; console.log(a); 浏览器先把var a先提升到最上面,然后在执行代码 var a; console.log(a); // undefined a = 10; console.log(a); // 10 在es6使用let声明块级作用域 { let a = 10 } console.log(a); 报错 */ let tabLi = document.getElementsByTagName('li'); let tabP = document.getElementsByTagName('p'); for (let i = 0; i < tabLi.length; i++){ // 将i保存到li标签对象中 // tabLi[i].index = i; es5的方法 // for循环比点击事件走的快。 i是全局作用域 tabLi[i].onclick = function () { for(let j=0; j<tabLi.length;j++){ tabLi[j].className = ''; tabP[j].className = ''; } this.className = 'active'; // tabP[this.index].className = 'active'; es5的方法 tabP[i].className = 'active'; // es6的方法,直接把var改成let就可以了 } } </script> </body> </html>
四、client、offset、scroll系统
他们的作用主要与计算盒模型、盒子的偏移量和滚动有关
1. client
clientTop 内容区域到边框顶部的距离 ,说白了,就是边框的高度。 clientLeft 内容区域到边框左部的距离,说白了就是边框的宽度。 clientWidth 内容区域+左右padding,可视宽度,不包含border。 clientHeight 内容区域+ 上下padding,可视高度。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> .box{ 200px; height: 200px; position: absolute; border: 10px solid red; /*margin: 10px 0px 0px 0px;*/ padding: 80px; } </style> </head> <body> <div class="box"> 以及风趣生动的课堂,在路飞,不是灌输知识,丰富的课程体系,博学多闻的实力讲师以及风趣生动的课堂,d识,而是点燃你的学习火焰。 </div> </body> <script type="text/javascript"> /* * clientTop 内容区域到边框顶部的距离 ,说白了,就是边框的高度 * clientLeft 内容区域到边框左部的距离,说白了就是边框的乱度 * clientWidth 内容区域+左右padding 可视宽度 * clientHeight 内容区域+ 上下padding 可视高度 * */ var oBox = document.getElementsByClassName('box')[0]; console.log(oBox.clientTop); // 10 console.log(oBox.clientLeft); // 10 console.log(oBox.clientWidth); // 360 console.log(oBox.clientHeight); // 360 </script> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> </body> <script type="text/javascript"> // 屏幕的可视区域 window.onload = function(){ // document.documentElement 获取的是html标签 console.log(document.documentElement.clientWidth); console.log(document.documentElement.clientHeight); // 窗口大小发生变化时,会调用此方法 window.onresize = function(){ console.log(document.documentElement.clientWidth); console.log(document.documentElement.clientHeight); } } </script> </html>
2. offset
偏移量
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> *{ padding: 0; margin: 0; } </style> </head> <body style="height: 2000px"> <div> <div class="wrap" style=" 300px;height: 300px;background-color: green"> <div id="box" style=" 200px;height: 200px;border: 5px solid red;position: absolute;top:50px;left: 30px;"> </div> </div> </div> </body> <script type="text/javascript"> window.onload = function(){ var box = document.getElementById('box') /* offsetWidth占位宽 内容+padding+border offsetHeight占位高 offsetTop: 如果盒子没有设置定位 到body的顶部的距离,如果盒子设置定位,那么是以父辈为基准的top值 offsetLeft: 如果盒子没有设置定位 到body的左部的距离,如果盒子设置定位,那么是以父辈为基准的left值 * */ console.log(box.offsetTop) console.log(box.offsetLeft) console.log(box.offsetWidth) console.log(box.offsetHeight) } </script> </html>
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style type="text/css"> * { padding: 0; margin: 0; } </style> </head> <body style=" 2000px;height: 2000px;padding: 10px; border: 1px solid red;"> <div style="height: 200px;background-color: red;"></div> <div style="height: 200px;background-color: green;"></div> <div style="height: 200px;background-color: yellow;"></div> <div style="height: 200px;background-color: blue;"></div> <div style="height: 200px;background-color: gray;"></div> <div id='scroll' style=" 200px;height: 200px;border: 1px solid red;overflow: auto;padding: 10px;margin: 5px 0px 0px 0px;"> <p> 学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界学习新技能,达成人生目标,开始用自己的力量影响世界 </p> </div> </body> <script type="text/javascript"> window.onload = function () { //实施监听滚动事件 var s = document.getElementById('scroll'); window.onscroll = function () { // console.log('上'+document.documentElement.scrollTop); // 页面卷起高度 // console.log('左'+document.documentElement.scrollLeft); // 包含border width + padding // console.log('宽'+document.documentElement.scrollWidth); // console.log('高'+document.documentElement.scrollHeight) // scrollHeight : 内容的高度+padding 不包含边框 console.log('上' + s.scrollTop); console.log('左' + s.scrollLeft); console.log('宽' + s.scrollWidth); console.log('高' + s.scrollHeight); }; } </script> </html>
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <style> #box{ 100px; height:100px; background-color: yellow; } </style> </head> <body> <div id="box">我的盒子</div> <button id="animate">动画吧</button> <button id="clear">清除定时器</button> <script> // // 一次性定时器 异步 // console.log('开始'); // // // 未来如果对数据的请求出现阻塞问题,可以用setTimeout来进行异步操作 // setTimeout(function () { // console.log('走到尽头了'); // },2000); // // console.log(22222); // 周期循环执行 let oDiv = document.getElementById('box'); let oAnimate = document.getElementById('animate'); let num = 0; let timer; oAnimate.onclick = function(){ timer = setInterval(function () { clearInterval(timer); // 先清定时器,再开定时器,页面不会出现问题。 // 控制盒子的步伐 num++; console.log(num); // 一直在加 oDiv.style.marginLeft = num + 'px'; },100); }; // clearInterval(); // clearTimeout(); let oClear = document.getElementById('clear'); oClear.onclick = function () { clearInterval(timer); } </script> </body>
/html>
六、BOM
1. BOM的介绍
浏览器对象模型。
-
操作浏览器部分功能的API。比如让浏览器自动滚动。
2. BOM的结构图
-
window对象是BOM的顶层(核心)对象,所有对象都是通过它延伸出来的,也可以称为window的子对象。
-
DOM是BOM的一部分。
3. window对象
-
window对象是JavaScript中的顶级对象。
-
全局变量、自定义函数也是window对象的属性和方法。
-
window对象下的属性和方法调用时,可以省略window。
弹出系统对话框
比如说,alert(1)
是window.alert(1)
的简写,因为它是window的子方法。
系统对话框有三种:
alert(); //不同浏览器中的外观是不一样的 confirm(); //兼容不好 prompt(); //不推荐使用
打开窗口、关闭窗口
1、打开窗口:
window.open(url,target);
参数解释:
-
url:要打开的地址。
-
target:新窗口的位置。可以是:
_blank
、_self
、_parent
父框架。
2、关闭窗口
window.close();
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <!--行间的js中的open() window不能省略--> <button onclick="window.open('https://www.luffycity.com/')">路飞学城</button> <button>打开百度</button> <button onclick="window.close()">关闭</button> <button>关闭</button> </body> <script type="text/javascript"> var oBtn = document.getElementsByTagName('button')[1]; var closeBtn = document.getElementsByTagName('button')[3]; oBtn.onclick = function(){ //open('https://www.baidu.com') //打开空白页面 open('about:blank',"_self") } closeBtn.onclick = function(){ if(confirm("是否关闭?")){ close(); } } </script> </html>
2. location对象
window.location
可以简写成location。location相当于浏览器地址栏,可以将url解析成独立的片段。
location对象的属性
-
href:跳转
-
hash 返回url中#后面的内容,包含#
-
host 主机名,包括端口
-
hostname 主机名
-
pathname url中的路径部分
-
protocol 协议 一般是http、https
-
search 查询字符串
案例 模拟a标签跳转
<script> var oSpan = document.getElementsByTagName("span")[0]; setInterval(function () { location.href = 'http://www.baidu.com'; },5000); </script>
location对象的方法
window.location.reload(); //全局刷新页面,相当于浏览器导航栏上 刷新按钮
history
1、后退:
-
history.back()
-
history.go(-1):0是刷新
2、前进:
-
history.forward()
-
history.go(1)
用的不多。因为浏览器中已经自带了这些功能的按钮:
<!-- history --> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <body> <a href="./index.html">新网页</a> <button id="forward">前进</button> <button id="refresh">刷新</button> <script> alert(1); function $(id) { return document.getElementById(id); } $('forward').onclick = function () { // 表示前进 window.history.go(1); }; $('refresh').onclick = function () { // 表示刷新,不常用因为是全局刷新 window.location.reload(); // 局部刷新使用ajax技术 } </script> </body> </html> <!-- index --> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <button id="back">后退</button> <script> function $(id) { return document.getElementById(id); } $('back').onclick = function () { // 表示后退 window.history.go(-1); } </script> </body> </html>
HTML5 存储技术 localStorage sessionStorage
对浏览器来说,使用 Web Storage 存储键值对比存储 Cookie 方式更直观,而且容量更大,它包含两种:localStorage 和 sessionStorage
sessionStorage(临时存储) :为每一个数据源维持一个存储区域,在浏览器打开期间存在,包括页面重新加载
localStorage(长期存储) :与 sessionStorage 一样,但是浏览器关闭后,数据依然会一直存在
API
sessionStorage 和 localStorage 的用法基本一致,引用类型的值要转换成JSON
let info = { name: 'Lee', age: 20, id: '001' }; sessionStorage.setItem('key', JSON.stringify(info)); localStorage.setItem('key', JSON.stringify(info));
var data1 = JSON.parse(sessionStorage.getItem('key')); var data2 = JSON.parse(localStorage.getItem('key'));
sessionStorage.removeItem('key');
localStorage.removeItem('key');
sessionStorage.clear();
localStorage.clear();
Storage 发生变化(增加、更新、删除)时的 触发,同一个页面发生的改变不会触发,只会监听同一域名下其他页面改变 Storage window.addEventListener('storage', function (e) { console.log('key', e.key); console.log('oldValue', e.oldValue); console.log('newValue', e.newValue); console.log('url', e.url); })
浏览器查看方法
-
进入开发者工具
-
选择 Application
-