文章目录
- JavaScript 特点
- ECMAScript 数据类型与数据转换
- ECMAScript 操作符和语句
- ECMAScript 函数
- ECMAScript 代码执行
- ECMAScript 闭包
- ECMAScript 对象
- ECMAScript 原型
- ECMAScript 继承、对象
- ECMAScript this指向、arguments类数组
- ECMAScript 数组
- ECMAScript try...catch和ES5严格模式
- ECMAScript 日期对象和计时器
- DOM 操作元素节点
- DOM 节点树
- DOM 元素节点的属性和方法
- BOM基本操作
- 脚本化CSS
- 事件分类
- json ==> {}
- 异步加载js
- js加载时间线
- 正则表达式 RegExp
- BOM window,localtion,screen,history,navigator
- Doctype
JavaScript 特点
1、浏览器组成
shell + 内核【渲染引擎(语法规则和渲染)、js引擎、其他模块】
主流浏览器 | 内核 |
---|---|
IE | trident |
Chrome | webkit、blink |
Firefox | Gecko |
Safari | webkit |
Opera | presto |
2、JavaScript — 解释型语言,单线程,也叫ECMAscript(ES)
1)编译型语言:通篇翻译,然后编译成文件 c c++
优点:快
不足:移植性不好,不跨平台
解释型语言:看一句编译一句 js php python
优点:跨平台
不足:稍微慢
Java两个都不是 .java — javac — 编译 — .class- — jvm — 解释执行
2)单线程:一次只能干一件事
3、js有三个部分
ECMAcript:原生部分
DOM:操作文档
BOM:操作浏览器
4、js执行队列,轮转时间片(类似吃饭)
5、js引用方式(2种)
1)页面级js:
<script>js代码区</script>
2)引用外部js文件:
<script src="js文件路径"></script>
6、编程形式
1)面向过程:c
2)面向对象:Java,c++
JavaScript:半对象半过程
7、错误类型
1)低级错误:语法解析错误,整个页面不执行
2)逻辑错误:发生错误之后的代码不执行
ECMAScript 数据类型与数据转换
1、变量命名规则
1)变量名必须以英文字母 _ $开头
2)变量名可以包括字母 _ $ 数字
3)不能不可以用系统的关键字保留字作为变量名
// 声明变量
var a;
// 变量赋值
a = 100;
// 单一var模式
var b = 1,c = 2,d = 3;
2、数据类型 — 解释型语言,数据类型由值决定
js基本数据类型:Number、String、Boolean、Undefined、Null、Object
原始值 值存在stack(栈) | 引用值 值存在heap(堆) |
---|---|
Number、String、Boolean、undefined、null | array、Object、function、date、RegExp … |
栈:先进后出first in last out,栈与栈之间的赋值是copy值
堆:在栈为引用值开辟空间,但值存在堆里,栈中是指向堆的地址,copy的是地址
1)Number 数字型
NaN — 数字型 — not a number
Infinity — 数字型 — 无穷
2)String 字符串类型
3)Boolean 布尔类型
4)Undefined 未定义,一个变量经过声明未赋值
5)Null 空值,主要为了占位
6)object 对象
// 定义对象
var deng = {
lastName : "Deng" ,
age : 40,
sex : undefined,
son : "xiaodeng",
handsome : function() {
return ture;
}
}
// 取对象值
console.log(deng.lastName);
// 数组
var arr = [1,2,3,4,53,8,"abc",undefined];
// 遍历数组
for(var i = 0; i < arr.length; i++){
console.log(arr[i]);
}
3、typeof() 判断数据类型,其他写法:typeof num
typeof()
数据 | 返回值 |
---|---|
number | number |
string | string |
false、true | boolean |
null、array | object |
undefined | undefined |
function | function |
4、Number() 转换为数字类型
数据 | 返回值 |
---|---|
number | 本身值 |
true | 1 |
null、false | 0 |
undefined | NaN |
5、parseInt() 转换为整数类型
第二个属性表示第一个属性值的进制,取值范围[2,36],默认为10进制
从第一位开始截取,遇到第一个非数字停止
数据 | 返回值 |
---|---|
非数值 | NaN |
整数/小数 | 整数 |
6、parseFloat() 转换为浮点数
7、toString() 转换为字符串
使用方法:demo.toString()
括号里可填进制,表示先转换进制,再转换为字符串
null和undefined不能用该方法
8、String() 转换为字符串
9、Boolean() 转换为布尔类型
10、toFixed(n) 保留n位小数
11、隐式转换 调用方法进行运算
方法 | 隐式调用方法 | 返回值 |
---|---|---|
isNaN() | Number() 内部调用Number()再与NaN比对 | true、false isNaN(null) ==> false isNaN(undefined) ==> true |
+ | String() | 值、字符串 |
++ – + -(一元正负) | Number() | 值 |
- * / % | Number() | 值 |
&& || ! | Boolean() | 值 |
< > <= >= | Number() | true、false |
== != | Number() | true、false NaN == NaN ==> flase undefined == null ==> true |
12、=== !== 不发生隐式转换,会判断数据类型是否相等
13、未定义变量时,以下不会报错
console.log(typeof(a));// undefined ==> 此为字符串类型
console.log(typeof(typeof(a)));// string
console.log(typeof(undefined));// string
ECMAScript 操作符和语句
1、运算操作符
+ - * / % = () ++ – += -= *= /= %=
运算操作符 | 功能 |
---|---|
+ | 数学运算和字符串连接 任何数据类型加字符串都是字符串 |
- * / % = () | 优先级()最高,=最低,先乘除后加减 赋值顺序:自右向左;计算顺序:自左向右 |
++ – | b = a++;b = a–;先执行语句再自增/减 b = ++a;b = --a;运算符在前,先自增/减再执行语句 |
+= -= *= /= %= |
2、比较运算符
< == >= <= !=
比较运算符 | 返回值 |
---|---|
< == >= <= != | false和true |
NaN == NaN;
// 返回false
3、逻辑运算符
&& 与 || 或 ! 非,undefined null NaN “” 0 false ==> false
逻辑运算符 | 返回值 |
---|---|
&& 与 | 运算值 |
|| 或 | 运算值 |
! 非 | false、true |
// 短路语句
2 > 1 && document.write('成哥很帅');
// || 用来写兼容
div.onclick = function(e) {
//非IE浏览器 e
// IE浏览器 window.event
var event = e || window.event;
}
4、条件语句 — if语句,switch case语句
1)if语句
// if语句
var score = parseInt(window.prompt('input'));
if(score <= 60){
document.write('are you kidding me?');
}else if(score <= 70){
document.write('蘑菇街');
}else if(score <= 80){
document.write('百度 携程 58赶集');
}else if(score <= 90){
document.write('腾讯 头条 美团 滴滴');
}else if(score <= 100){
document.write('alibaba');
}else{
document.write('error!!')
}
2)switch case语句
// switch case语句
var n = "a";
switch(n){
case 1:
console.log('a');
case "a":
console.log('b');
break;// 不加break会继续执行后面的语句
case true:
console.log('c');
}
5、循环语句 — for循环,while循环,do while循环
1)for循环
// for循环
for(var i = 0; i < 10; i++){
document.write(i + ' ');
}
for(var i = 0; i < 100; i++){
if(i % 3 == 0 || i % 5 ==0 || i % 7 ==0 ){
document.write(i + ' ');
}
}
// 思维拓展
var i = 100;
for( ; i--; ){
document.write(i +' ');
}
2)while循环
// while循环
var i = 0;
while(i < 10){
document.write(i +' ');
i++;
}
3)do while循环
// do while循环--先执行一次
var i = 0;
do{
document.write(i +' ');
i++;
}while(i < 10)
6、break和continue
break:结束所有循环
continue:结束本次循环,进入下次循环
ECMAScript 函数
1、函数
// 函数声明
function test(形参) {函数体} // 函数名为test
// 函数表达式
var test = function abc() {函数体} // 表达式,忽略函数名abc
// 匿名函数表达式
var demo = function () {函数体} // 匿名函数,函数名为demo
2、参数,返回值return
形参:定义函数时输入的参数
实参:调用函数时输入的参数
// i形参 a实参
function test(i) {
return i;
}
var a = 123;
test(a);
// 调用函数时会把实参存在arguments数组里
arguments.length;// 返回实参长度
test.length;// 返回形参长度
3、递归函数
特点:先执行的最后被执行完
1)找规律:找到表达式
2)找出口:找到已知条件
// 斐波那契数列 n = (n - 1) + (n - 2)
function fb(n) {
if(n == 2 || n == 1){
return 1;
}
return fb(n - 1) + fb(n - 2);
}
// n的阶乘 n! = n * (n - 1)!
function jc(n) {
if(n == 1 || n == 0){
return 1;
}
return n * jc(n - 1);
}
4、数学函数
1)Math.ceil() ==> 向上取整
var i = Math.ceil(123.234);
console.log(i);// 124
2)Math.floor() ==>向下取整
var i = Math.floor(123.676);
console.log(i);// 123
3)Math.random() ==> 产生一个(0,1)的随机数
var i = Math.random();
console.log(i);
4)toFixed(n) ==> 保留n位小数
// toFixed有时候会出现精度问题,因此最好用Math.ceil()和Math.floor()方法
var num = 0.14;
console.log(num.toFixed(2)*100);// 14.000000000000002
5)js能计算的位数:小数点前16位,小数点后无穷位
ECMAScript 代码执行
1、作用域
1)全局变量
2)局部变量:函数里定义的变量
3)函数里面可以访问全局变量,但全局变量不能访问函数里面的变量
4)函数嵌套时,里面可以访问外面的变量,外面不可以访问里面的变量
2、js执行三部曲
1)语法分析:扫描全文,看有没有语法错误
2)预编译:函数声明整体提升,变量声明提升
imply global暗示全局变量:即任何变量,如果未经声明就赋值,此变量就为全局(window)所有
一切声明的全局变量,全是window的属性,window = 全局
var a = 10; === window{a : 10}
3)解释语言
3、预编译,先GO后AO
1)全局预编译过程 GO === window
①创建GO(Global Object)对象(执行期上下文)
②找变量声明,将变量名作为GO属性名,值为undefined
③找函数声明
/**
* GO{
* a : undefined,
* c : 234
* }
*/
function test() {
console.log(b);// undefined
if(a){
var b = 100;
}
c = 234;// 暗示全局变量
console.log(c);// 234
}
var a;
test();
/**
* AO{
* b : undefined
* }
*/
a = 10;
console.log(c);// 234
2)函数内预编译过程 AO
①创建AO(Activation Object)对象(执行期上下文)
②找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
③将实参值和形参统一(将实参传进形参)
④在函数体里面找函数声明(函数表达式不看),值赋予函数体
function fn(a) {
console.log(a);// function a() {}
var a = 123;
console.log(a);// 123
function a () {
}
console.log(a);// 123
var b = function () {}
console.log(b);// function () {}
function d() {
}
}
fn(1);
/**
* AO{
* a : function a() {},
* b : undefined,
* d : function d() {}
* }
*/
function test(a, b) {
console.log(a);// function a() {}
console.log(b);// undefined
var b = 234;
console.log(b);// 234
a = 123;
console.log(a);// 123
function a() {
}
var a;
b = 234;
var b = function () {
}
console.log(a);// 123
console.log(b);// function () {}
}
test(1);
/**
* AO{
* a : function a() {},
* b : undefined
* }
*/
4、作用域精解
[[scope]]每个javascript函数都是一个对象,对象中有些属性我们可以访问,但有些不可以,这些属性仅供javascript引擎存取,[[scope]]就是其中一个。[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合
function a() {
function b() {
function c() {
}
c();
}
b();
}
a();
// a defined a.[[scope]] --> 0:GO
// a.doing a.[[scope]] --> 0:aAO
// 1:GO
// b.defined b.[[scope]] --> 0:aAO
// 1:GO
// b.doing b.[[scope]] --> 0:bAO
// 1:aAO
// 2:GO
// c.defined c.[[scope]] --> 0:bAO
// 1:aAO
// 2:GO
// c.doing c.[[scope]] --> 0:cAO
// 1:bAO
// 2.aAO
// 3:GO
ECMAScript 闭包
1、闭包
当内部函数被保存到外部时,将会生成闭包,导致作用域链不释放,造成内存泄漏
function a() {
var num = 100;
function b() {
num++;
console.log(num);
}
return b;
}
var demo = a();
console.log(demo);
demo();// 101
demo();// 102
demo();// 103
2、闭包作用
1)实现公有变量
// eg.实现累加器
function add() {
var count = 0;
function demo() {
count++;
console.log(count);
}
return demo;
}
var counter = add();
counter();// 1
counter();// 2
2)可以做缓存(存储结构)
function test() {
var num = 100;
function a() {
num++;
console.log(num);
}
function b() {
num--;
console.log(num);
}
return [a,b];
}
var myArr = test();
myArr[0]();// 101
myArr[0]();// 102
myArr[0]();// 103
myArr[1]();// 102
3)可以实现封装,属性私有化 eg.prepareWife和继承
function Deng(name, wife) {
var prepareWife = 'xiaozhang';
this.name = name;
this.wife = wife;
this.divorce = function () {
this.wife = prepareWife;
}
this.changePrepareWife = function(target) {
prepareWife = target;
}
this.sayPrepare = function () {
console.log(prepareWife);
}
}
var deng = new Deng('deng', 'xiaoliu');
// Yahoo定义的封装inherit,闭包实现属性私有化
father.prototype.lastName = 'ji';
function Father() {
}
function Son() {
}
var inherit = (function () {
var F = function () {
};
return function (Target, Origan) {
F.prototype = Origan.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
4)模块化开发,防止污染全局变量
var init = (function () {
var name = 'abc';
function callName() {
console.log(name);
}
return function () {
callName();
}
}());
init();
var initDeng = (function () {
var name = 123;
function callName() {
console.log(name);
}
return function () {
callName();
}
}());
3、立即执行函数
执行一次之后被销毁 ==> 针对初始化功能的函数
1)两种写法
var num = (function 函数名(形参){函数体}(实参));// 函数名可省
// 第一种 -- W3C推荐用法
(function () {
// 函数体
}());
// 第二种
(function () {
// 函数体
})();
2)只有表达式才能被执行符号执行,能被执行符号执行的函数会忽略函数名,() ==> 执行符
代码语句 | 执行结果 |
---|---|
function test(){}();// 函数声明 | 报错 括号里有内容系统会自动断句不会报错,也不会执行函数 |
±! function test(){}(); | 正负非,会执行 |
var num = function test(){}(); | 函数表达式,会执行 |
4、闭包产生的问题
// 函数调用时才会执行,输出结果为:10 10 10 10 10 10 10 10 10 10/
function test() {
var arr = [];
for(var i = 0; i < 10; i++){
arr[i] = function () {
document.write(i + ' ');
}
}
return arr;
}
var myArr = test();
for (var j = 0; j < 10; j++){
myArr[j]();// 函数传进数据但不执行
}
// 用立即执行函数解决闭包产生的问题
function test() {
var arr = [];
for(var i = 0; i < 10; i++){
(function (n) {
arr[n] = function () {
document.write(n + ' ');
};
})(i);
}
return arr;
}
var myArr = test();
for (var j = 0; j < 10; j++){
myArr[j]();
}
ECMAScript 对象
1、对象属性或方法的增删改查
var mrDeng = {
// 在对象中函数叫方法,其他叫属性
name : "MrDeng",
age : 40,
sex : "male",
health : 100,
// 这里的this指向mrDeng
smoke : function () {
console.log("I'm smoking!");
this.health--;// = mrDeng.health--;
},
drink : function () {
console.log("I'm drinking!");
this.health++;// = mrDeng.health--;
}
}
// 增加对象属性或方法
mrDeng.wife = "xiaowang";
mrDeng.play = function () {
console.log("I'm playing!");
};
// 修改对象属性或方法
mrDeng.age = 30;
mrDeng.play = function () {
console.log("I'm happy!");
};
// 删除对象属性或方法
delete mrDeng.wife;
delete mrDeng.play;
2、对象的创建方法
1)对象字面量/对象直接量/plainObject ==> 推荐用法
var obj = {}
2)构造函数
①系统自带的构造函数 eg.Object() Array() Number()
②自定义构造函数 遵循大驼峰式命名规则
// a.系统自带的构造函数 eg.Object() Array() Number()
var obj = new Object();
// b.自定义 遵循大驼峰式命名规则
// eg.造车
function Car(color) {
this.color = color;
this.name = 'BMW';
this.height = '1400';
this.lang = '4900';
this.weight = 1000;
this.health = 100;
this.run = function() {
this.health--;
}
}
var car = new Car('red');// 必须以new关键字创建对象
var car1 = new Car('green');
// eg.学生信息输入
function Student(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.grade = 2017;
}
var student = new Student('zhangsan', 18, 'male');
3、构造函数内部原理,new之后内部流程
1)在函数体最前面隐式的加上var this = {}
2)执行 this.xxx = xxx;
3)隐式的返回this
function Student(name, age, sex) {
// var this = {}
// 执行 this.xxx = xxx;
this.name = name;
this.age = age;
this.sex = sex;
this.grade = 2017;
// return this;
}
var student = new Student('zhangsan', 18, 'male');
console.log(new Student('xiaohong', 19, 'male').age);
// 根据构造函数原理用that模拟构造函数
function Person(name, age) {
var that = {};
that.name = name;
that.age = age;
return that;
}
var person = new Person('xiaohong', 19);
var person = new Person('lisi', 45);
4、包装类
new Number,new String,new Boolean,undefined和null不能设置属性和方法
// 包装类的过程
var num = 4;
num.len = 3;
// 系统内部会先new Number(4).len = 3; 然后delete
console.log(num.len);
// 访问new.len时会再次new Number(4).len; 但Number没有len这个属性,因此返回undefined
var str = 'abcd';
str.length = 2;
// 系统内部会先new String('abcd').lenth = 2; 然后delete
console.log(str.length);
// 访问str.length时会再次new String('abcd').lenth; String有该属性,因此返回4
ECMAScript 原型
1、原型
function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象
// Person.prototype = {} ——> 原型,是祖先
Person.prototype.lastname = "hehe";
function Person(name,sex,age) {
this.name = name;
this.sex = sex;
this.age = age;
}
var person = new Person('xiaohong', 'male', 40);
1)利用原型特点和概念,可以提取共有属性
// 原型写法一
Car.prototype.height = 1400;
Car.prototype.carName = 'BMW';
Car.prototype.lang = 4900;
// 原型写法二
Car.prototype = {
height : 1400,
carName : 'BMW',
lang : 4900
}
function Car(owner, color) {
this.owner = owner;
this.color = color;
}
var car1 = new Car('lisi', 'red');
var car1 = new Car('zhangsan', 'green');
// 原型增加属性
Car.prototype.speed = 200;
// 原型修改属性
Car.prototype.lang = 5700;
// 原型删除属性
delete Car.prototype.lang;
2)对象查看原型
// 对象如何查看原型 ——> 隐式属性 __proto__ ——> 可以改变__proto__的指向
// person.name会被改变
Person.prototype.name = 'sunny';
function Person() {
// var this = {
// __proto__ : Person.prototype
// };
}
var person = new Person();
Person.prototype.name = 'cherry';
// person.name不会被改变
Person.prototype.name = 'sunny';
function Person() {
}
var person = new Person();
// 此法Person.prototype指向了新的空间
Person.prototype = {
name : 'cherry'
}
// person.name会被改变
Person.prototype.name = 'sunny';
function Person() {
}
// Person.prototype指向了新的空间,但person是改变之后才创建的
Person.prototype = {
name : 'cherry'
}
var person = new Person();
3)查看对象的构造函数 constructor
2、原型链
1)原型链的构成
// Grand.prototype.__proto__ ==> Object.prototype(所有原型链的终端)
Grand.prototype.lastName = "deng";
function Grand() {
}
var grand = new Grand();
Father.prototype = grand;
function Father() {
this.name = 'xuming'
this.fortune = {
card1 : 'visa'
}
}
var father = new Father();
Son.prototype = father;
function Son() {
this.hobbit = 'smoke'
}
var son = new Son();
son.fortune.card2 = 'jianhang';// 通过调用父级的方法改变引用值,属于调用修改
2)原型链增删改查,子级增删改查不影响父级
原始值只能通过父级覆盖修改,引用值子级可以通过调用来修改
// a.sayName() sayName里面的this,谁调用这个方法,this就指向谁
Person.prototype = {
name : 'a',
sayName : function() {
console.log(this.name);
}
}
function Person() {
}
var person = new Person();
Person.prototype = {
height : 100
}
function Person() {
this.eat = function() {
this.height++;
}
}
var person = new Person();
3、创建对象三种方法
1)对象字面量创建对象,推荐使用
var obj = {}; ==> new Object();
Person.prototype = {}; ==> Objec.tprototype
function Person() {
}
2)构造函数创建对象
var obj1 = new Object();
3)Object.create(原型);
// obj1以obj为原型创建对象
var obj = {name : 'deng', age = 20}
var obj1 = Object.create(obj);
4、绝大多数对象的最终都会继承自Object.prototype
var obj = Object.create(null);// obj没有原型
obj.__proto__ = {name : 'deng'};// 人为可添加,但不存在继承特性,不能被继承
var obj1 = Object.create(obj);
5、null和undefined不能经过包装类,没有原型,没有toString()方法
6、JavaScript重写
// 重写Number的toString方法
Number.prototype.toString = function () {
}
var obj = 123;
// 系统自带的重写
Object.prototype.toString
// 重写
Number.prototype.toString
Array.prototype.toString
Boolean.prototype.toString
String.prototype.toString
7、call和apply方法
call和apply 借用别人的函数体现自己的功能
作用:改变this指向
区别:后面传的参数形式不同,call 需要把实参按照形参的个数传进去,apply 需要传一个argument
apply 需要传一个argument
function Person(name, age){
// call之后this == obj,
this.name = name;
this.age = age;
}
var person = new Person('deng', 100);
var obj = {
}
// Person里this默认指向window,call会让Person里面的this指向obj
// call第一位改变this指向,后面把实参按照形参的个数传进去
Person.call(obj, 'cheng', 300);
// apply第一位改变this指向,后面传一个argument
Person.apply(obj, ['cheng', 300])
// test() ==> test.call();
function Person(name, age, sex){
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade){
Person.call(this, name, age, sex);
//Person.apply(this, [name, age, sex])
this.tel = tel;
this.grade = grade;
}
var student = new Student('sunny', 123, 'male', 139, 2017);
// 造车
function Wheel(wheelSize, style){
this.wheelSize = wheelSize;
this.style = style;
}
function Sit(c, sitColor){
this.c = c;
this.sitColor = sitColor;
}
function Model(height, width, len){
this.height = height;
this.width = width;
this.len = len;
}
function Car(wheelSize, style, c, sitColor, height, width, len){
Wheel.call(this, wheelSize, style);
// Wheel.apply(this, [wheelSize, style]);
Sit.call(this, c, sitColor);
// Sit.apply(this, [c, sitColor]);
Model.call(this, height, width, len);
// Model.apply(this, [height, width, len]);
}
var car = new Car(100,'花里胡哨', '真皮', 'red', 1800, 1900, 4900);
ECMAScript 继承、对象
1、继承发展史
1)传统形式 ==> 原型链
过多的继承了没用的属性
Grand.prototype.lastName = 'ji';
function Grand () {
}
var grand = new Grand();
Father.prototype = grand;
function Father () {
}
var father = new Father();
Son.prototype = father;
function Son () {
}
var son = new Son();
2)借用构造函数
不能继承借用的构造函数的原型
每次构造函数都要多走一个函数
每次构造函数都要多走一个函数
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
function Student(name, age, sex, tel, grade) {
Person.call(this, name, age, sex);
this.tel = tel;
this.grade = grade;
}
var student = new Student();
3)共享原型
不能随便改动自己的原型
Son增删改查prototype会影响Father的prototype,因为二者指向同一个空间
father.prototype.lastName = 'ji';
function Father() {
}
function Son() {
}
Son.prototype = Father.prototype;
var father = new Father();
var son = new Son();
//继承函数 inherit/extend关键字
father.prototype.lastName = 'ji';
function Father () {
}
function Son () {
}
function inherit(Target, Origan) {
Target.prototype = Origan.prototype;
}
inherit(Son, Father);
var son = new Son();
4)圣杯模式
// Father.prototype
// function F() {}
// F.prototype = Father.prototype;
// Son.prototype = new F();
// Father Son
father.prototype.lastName = 'ji';
function Father () {
}
function Son () {
}
function inherit(Target, Origan) {
function F () {
}
F.prototype = Origan.prototype;
Target.prototype = new F();
// son.__proto__ ==> new F().__proto__ ==> Father.prototype
Target.prototype.constuctor = Target;
// 保存究极父级
Target.prototype.uber = Origin.prototype;
}
inherit(Son, Father);
var son = new Son();
var father = new Father();
// Yahoo定义的封装inherit,闭包实现属性私有化
father.prototype.lastName = 'ji';
function Father () {
}
function Son () {
}
var inherit = (function () {
var F = function () {};
return function(Target, Origan){
F.prototype = Origan.prototype;
Target.prototype = new F();
Target.prototype.constuctor = Target;
Target.prototype.uber = Origin.prototype;
}
}());
2、管理变量,防止污染全局,适用于模块开发
1)命名空间(老方法,不使用)
var org = {
department1 : {
jicheng : {
name : 'abc',
age : 123
},
xuming : {
}
}
department1 : {
zhangsan : {
},
lish : {
}
}
}
2)闭包方法,防止污染全局变量
var init = (function () {
var name = 'abc';
function callName() {
console.log(name);
}
return function () {
callName();
}
}());
init();
var initDeng = (function () {
var name = 123;
function callName() {
console.log(name);
}
return function () {
callName();
}
}());
3、模仿jQuery连续调用
var deng = {
smoke : function () {
console.log('smoking ');
return this;// deng
},
drink : function () {
console.log('drinking ');
return this;// deng
},
perm : function () {
console.log('perming ');
return this;// deng
}
}
deng.smoke().drink().perm();
4、属性的表示方法
1)obj.prop
var obj = {
name = 'abc'
}
obj.name;// obj.name ==> obj['name'];
2)obj[“prop”]
var deng = {
wife1 : {name : 'xiaohong'},
wife2 : {name : 'xiaolan'},
wife3 : {name : 'xiaowang'},
wife4 : {name : 'xiaozi'},
sayWife : function (num) {
return this['wife' + num];
}
}
5、对象的遍历,方法
1)for in 对象枚举/遍历 enumeration
// 对象遍历
var obj = {
name : '1sn',
age : 12,
sex : 'male',
height : 12,
weight : 75,
__proto__ : {
lastName : 'deng'
}
}
for(var prop in obj){
//console.log(obj.prop); ==> console.log(obj['prop']]); 因此结果为undefined
console.log(obj[prop]);
}
var obj1 = {
a : 123,
b : 234,
c : 345
}
for(var key in obj1){
obj1[key] ++;
}
// 数组遍历
var arr = [1,2,3,4,5,6,7];
for(var i = 0; i< arr.length; i++){
console.log(arr[i]);
}
2)hasOwnProperty方法
判断属性是否是自己的,返回true/false,过滤性方法
var obj = {
name : '1sn',
age : 12,
sex : 'male',
height : 12,
weight : 75,
__proto__ : {
lastName : 'deng'
}
}
Object.prototype.abc = 123;
for(var prop in obj){
//console.log(obj.prop); ==> console.log(obj['prop']); 因此结果为undefined
if(!obj.hasOwnProperty(prop)){
console.log(obj[prop]);
}
}
3)in方法
判断能不能访问属性,返回true/false
4)instanceof方法
A instanceof B,判断A对象是不是B构造函数构造出来的
本质上是看A的原型链上有没有B的原型
function Person() {
}
var person = new Person();
obj = new Object();
console.log(obj instanceof Person);
console.log(person instanceof Person);
console.log(person instanceof Object);
6、判断是数组还是对象,三种方法
var obj = {};// []
// constructor方法
console.log(obj.constructor);
// instanceof方法
console.log(obj instanceof Array);// false
console.log(obj instanceof Object);// true
// toString方法
Object.prototype.toString.call([]);
// 内部原理
// Object.prototype.toString = function () {
// // 识别this
// // 返回相应结果
// }
ECMAScript this指向、arguments类数组
1、this指向
1)函数预编译过程中,this指向window
2)全局作用域里,this指向window
3)call/apply可以改变函数运行时this指向
4)obj.func(); func()里面的this指向obj,谁调用this就指向谁
var name = "222";
var a = {
name : "111",
say : function () {
console.log(this.name);
}
}
var fun = a.say;
fun();
a.say();
var b = {
name : "333",
say : function (fun) {
fun();
}
}
b.say(a.say);
b.say = a.say;
b.say();
2、arguments类数组
1)callee 指向函数自身引用
arguments.callee ==> 返回函数自身
var num = (function (n) {
if(n == 1){
return 1
}
return n * arguments.callee(n - 1);
}(8));
2)length 返回arguments数组的长度
3)func.caller func被引用的环境
function test() {
demo();
}
function demo() {
console.log(demo.caller);// function test
}
test();
ECMAScript 数组
1、三目运算符 条件判断 ? 是 : 否 并返回值
var num = 1 < 0 ? 2 + 2 : 1 + 1;// 2
var num = 1 > 0 ? ('10' > '9' ? 1 : 0) : 2;// 0
2、数组
1)数组的定义
①字面量 ==> 推荐用法
// 字面量
var arr = [];
②构造函数,只传一个参数表示数组长度,传n个参数表示数组内容
// 构造函数
var arr = new Array(length/content);
2)数组的读和写
arr[num]// 不可以溢出读 结果undefined
arr[num] = xxx;// 可以溢出写
3)数组常用的方法
改变原数组(7个):push,pop,shift,unshift,sort,reverse,splice
不改变原数组:concat,join ==> split,toString,slice
// 改变原数组
// push 在数组后面添加东西,可添加多个
var arr = [1,2];
arr.push(10);
arr.push(11);
arr.push(9,4);
Array.prototype.Push = function () {
for(var i = 0; i < arguments.length; i++){
this[this.length] = arguments[i];
}
return length;
}
// pop 把数组最后一位切除
arr.pop();
// unshift 在数组前面添加东西,可添加多个
// shift 把数组第一位切除
// sort 数组排序,默认按ASCII码升序
// 有接口可以设置排序规则,传参规则符合冒泡排序
// 1.必须写两个形参
// 2.看返回值:返回值为负,前面的数放在前面;返回值为正,后面的数放在前面;为0,不懂
var arr = [2,1,3,4,5,-3,0,18];
arr.sort(function (a, b) {
// if(a > b){
// return 1;
// }else{
// return -1;
// }
return a - b;// 升序
});
// 数组乱序
var arr = [2,1,3,4,5,-3,0,18];
arr.sort(function () {
return 0.5 - Math.random();
});
// 按年龄排序
var cheng = {
name : 'cheng',
age : 18,
sex : 'male',
face : 'handsome'
}
var deng = {
name : 'deng',
age : 28,
sex : 'male',
face : 'amazing'
}
var zhang = {
name : 'zhang',
age : 24,
sex : 'female',
face : 'amazing'
}
var arr = [cheng, deng, zhang];
arr.sort(function(a, b){
return a.age - b.age;
});
// reverse 数组逆转顺序
// splice ==> arr.splice(从第几位开始, 截掉多少长度, 在切口处添加新数据)
arr.splice(1,2);
splice = function (pos) {
pos += pos > 0 ? 0 : this.length;
}
// 不改变原数组
//concat 连接数组
var arr1 = [1,23,4,5];
var arr2 = ['cn','edf',34,5];
arr1.concat(arr2);
// join ==> arr.join("连接标记")
var arr = [1,23,3,4,55,'f','g'];
str = arr.join("-");
// split 与join互逆,string的方法
arr = str.split("-");
// toString 数组内容转为字符串
// slice ==> arr.slice(从该位开始截取, 截取到该位)
var newArr = arr.slice(2, 4);
var newArr = arr.slice();// 整个截取
3、类数组
属性要为索引(数字)属性, 必须要有length,最好加上push,Array其他属性也可添加
e.g arguments
var obj = {
"0" : 'a',
"1" : 'b',
"2" : 'c',
"length" : 3,
"push" : Array.prototype.push
};
obj.push('d');
var obj = {
"3" : 'a',
"4" : 'b',
"length" : 2,
"push" : Array.prototype.push
};
obj.push('c');
obj.push('d');
// obj = {
// 2: "c"
// 3: "d"
// 4: "b"
// length: 4
// push: ƒ push()
// [[Prototype]]: Object
//返回上述结果的原因 ==> push的内部原理
Array.prototype.Push = function () {
for(var i = 0; i < arguments.length; i++){
this[this.length] = arguments[i];
}
return length;
}
ECMAScript try…catch和ES5严格模式
1、try…catch
Error.name的六种值对应的信息
1)EvalError:eval()的使用与定义不一致
2)RangeError:数值越界
3)ReferenceError:非法或不能识别的引用数值,变量/函数未定义就使用
4)SyntaxError:发生语法解析错误,中文标点符号
5)TypeError:操作数类型错误,数组方法操作对象
6)URIError:URI处理函数使用不当
//try{}catch(e) {}finally{}
// 在try里面发生错误,不会执行错误后的try里面的代码
// try里面发生错误以后会执行catch(e),否则不执行
try{
console.log('a');
console.log(b);// 代码出错,try里面出错误之后的代码不执行
console.log('c');
}catch(e) {// error error.message error.name ==> error
console.log(e.name + " " + e.message);
}
console.log('d');
2、es5严格模式
es3.0 和 es5.0产生冲突的部分使用es5.0,否则使用es3.0
目前调用的方法基于es3.0 + es5.0的新增方法使用的
两种用法:全局严格模式;局部函数内严格模式(推荐)
"use strict";// 页面/函数启动es5.0,写在页面逻辑最顶端或函数内部最顶端
1)es0.5不支持
①with(){} 改变作用域链,让()内的对象作为{}的作用域链的最顶端,用来简化代码
var obj = {
name : "obj"
}
var name = "window";
function test() {
var name = "scope";
with(obj) {
console.log(name);
}
}
test();
with(document){
write('e');
}
②arguments.callee
③func.caller
④变量赋值前必须声明
⑤局部this必须被赋值,Person.call(null/undefined)赋值什么就是什么,不会包装类
"use strict";
function Test() {
console.log(this);
}
Test.call(123);
⑥拒绝重复属性和参数,目前不会报错
"use strict";
function test(name, name){
console.log(name);
}
var obj = {
name : "123",
name : "gnnj"
}
ECMAScript 日期对象和计时器
1、日期对象是系统提供好的,Date构造出的对象拥有的方法
1)Date() 返回当前日期和时间
2)toString() 返回为字符串类型
3)get方法
getDate(); 从Date对象返回一个月中的某一天(1~31)
getDay(); 从Date对象返回一个星期的某一天(0~6)
getMonth() 从Date对象返回月份(0~11)
getFullYear(); 从Date对象返回四位数年份
getHours(); 返回Date对象的小时(0~23)
getMinutes(); 返回Date对象的分钟(0~59)
getSeconds(); 返回Date对象的秒数(0~59)
getMilliseconds(); 返回Date对象的毫秒(0~999)
getTime(); 返回1970年1月1日至今的毫秒数,时间戳
// 测试电脑运行速度
var firstTime = new Date().getTime();
for (var i = 0; i < 1000000; i++){}
var lastTime = new Date().getTime();
console.log(lastTime - firstTime);
4)set方法
setDate(); 设置Date对象月中的某一天(1~31)
setMonth(); 设置Date对象月份(0~11)
setFullYear(); 设置Date对象四位数年份
setHours(); 设置Date对象的小时(0~23)
setMinutes(); 设置Date对象的分钟(0~59)
setSeconds(); 设置Date对象的秒数(0~59)
setMilliseconds(); 设置Date对象的毫秒(0~999)
setTime(); 以毫秒设置Date对象
2、js定时器
全局对象window上的方法,内部函数this指向window
两个定时器会依次分配唯一标识
1)定时循环器
setInterval(); 定时循环器,系统会分配唯一标识
clearInterval(); 清除定时循环器
var i = 1;
var timer = setInterval(function(){
if(i > 4){
// clearInterval(1);
clearInterval(timer);
}
console.log(i);
i++;
},1000);
2)定时执行器
setTimeout(); 定时器,推迟一段时间执行
clearTimeout(); 清除定时器
setTimeout(function(){
console.log('a');
}, 2000);
DOM 操作元素节点
1、DOM ==> Document Object Model文档操作模型
操作HTML和XHTML,可以改变行间样式,但不能操作CSS
2、查看元素节点
document代表整个文档
1)document.getElementById(); ==> id名
元素id 在IE8以下浏览器,不区分id大小写,也可返回匹配name属性的元素
2)document.getElementsByTagName(); ==> 标签名
3)document.getElementsByName(); ==> name名
需注意,只有部分标签name可生效(表单,表单元素,img,iframe)
4)document.getElementsByClassName(); ==> 类名
IE8和IE8以下的IE版本中没有,可以多个class一起
5)document.querySelector(); ==> css选择器
在IE7和IE7以下的版本中没有,不是实时的
6)document.querySelectorAll(); ==> css选择器
在IE7和IE7以下的版本中没有,不是实时的
3、增加元素节点
1)document.createElement(); 创建元素节点
2)document.createTextNode(); 创建文本节点
3)document.createComment(); 创建注释节点
4)document.createDocumentFragment(); 创建文档碎片节点
var div = document.createElement('div');
var text = document.createTextNode('哈哈哈哈');
var comment = document.createComment('this is a comment');
4、插入元素节点
1)ParentNode.appendChild(); 在父元素内部末尾插入节点,可用作剪切操作
2)ParentNode.insertBefore(a, b); ==> insert a before b
var div = document.createElement('div');
document.body.appendChild(div);
5、删除元素节点
1)parent.removeChild(); 父节点删除子节点,被剪切出来
2)child.remove(); 子节点自我删除,彻底删除
6、替换元素节点
parent.replaceChild(new, origin); ==> new replace origin
DOM 节点树
1、遍历节点树
1)parentNode ==> 父节点,最顶端的parentNode为#document
2)childNodes ==> 子节点们(直系)
3)firstChild ==> 第一个子节点
4)lastChild ==> 最后一个子节点
5)nextSibling ==> 后一个兄弟元素
6)previousSibling ==> 前一个兄弟元素
2、基于元素节点树的遍历
1)parentElement ==> 返回当前元素的父元素节点(IE不兼容),最顶端的parentElement为html
2)children ==> 只返回当前元素的元素子节点
3)node.childElementCount ==> node.children.length当前元素节点的子元素节点个数(IE不兼容)
4)firstElementChild ==> 返回的是第一个元素节点(IE不兼容)
5)lastElementChild ==> 返回的是最后一个元素节点(IE不兼容)
6)nextElementSibling ==> 返回后一个兄弟元素节点(IE不兼容)
7)previousElementSibling ==> 返回前一个兄弟元素节点(IE不兼容)
3、节点的类型(nodeType返回值)
元素节点 ==> 1 div,span,strong…
属性节点 ==> 2
文本节点 ==> 3 text
注释节点 ==> 8 comment
document ==> 9
DocumentFragment ==> 11
获取节点类型 nodeType
4、节点的四个属性
nodeName 元素的标签名,以大写形式表示,只读
nodeValue Text节点或Comment节点的文本内容,可读写
nodeType 该节点的类型,只读
attributes Element节点的属性集合,可读写
5、节点的一个方法
Node.hasChildNodes(); 返回值为true/false
6、DOM操作元素节点方法在节点树上的定义
1)getElementById方法
定义在Document.prototype上,即Element节点上不能使用
2)getElementsByName方法
定义在HTMLDocument.prototype上,即非html中的document以外不能使用(xml document,Element)
3)getElementsByTagName方法
定义在Document.prototype 和 Element.prototype上
4)HTMLDocument.prototype
定义了一些常用的属性body、head,分别指代HTML文档中的标签
document.body ==>
document.head ==>
5)Document.prototype
定义了documentElement属性,指代文档的根元素,在HTML文档中,他总是指代元素
document.documentElement ==>
6)getElementsByClassName、querySelectorAll、querySelector
在Document,Element类中均有定义
DOM 元素节点的属性和方法
1、Element节点的一些属性
innerHTML
innerText(火狐不兼容) / 火狐支持textContent(老版本IE不好使)
2、Element节点的一些方法
ele.setAttribute(); 设置行间属性
ele.getAttribute(); 获取行间属性
div.setAttribute('class', 'only');
div.getAttribute('class');
BOM基本操作
1、查看滚动条的滚动距离
window.pageXOffset/pageYOffset IE8及IE8以下不兼容
document.body/documentElement.scrollLeft/scrollTop IE8及IE8以下使用
兼容性比较混乱,用时取两个值相加,因为不可能存在两个同时有值
// 封装兼容性方法,求滚动轮滚动距离getScrollOffset()
function getScrollOffset() {
if(window.pageXOffset) {
return{
x : window.pageXOffset,
y : window.pageYOffset
}
}else{
return {
x : document.body.scrollLeft + document.documentElement.scrollLeft,
y : document.body.scrollTop + document.documentElement.scrollTop
}
}
}
2、查看视口的尺寸
window.innerWidth/innerHeight IE8及IE8以下不兼容
document.documentElement.clientWidth/clientHeight 标准模式下,任意浏览器都兼容
document.body.clientWidth/clientHeight 适用于怪异/混杂模式下的浏览器 不写<!DOCUMENT html>
// 封装兼容性方法,返回浏览器视口尺寸getViewportOffset()
function getViewportOffset() {
if(window.innerWidth){
return{
w : window.innerWidth,
h : window.innerHeight
}
}else if(document.compatMode === "CSS1Compat"){
return{
// 标准模式
w : document.documentElement.clientWidth,
h : document.documentElement.clientHeight
}
}else{
return{
// 怪异模式 document.compatMode === "BackCompat"
w : document.body.clientWidth,
h : document.body.clientHeight
}
}
}
3、查看元素的几何尺寸
domEle.getBoundingClientRect();
兼容性很好
该方法返回一个对象,对象里面有left,top,right,bottom,height,width等属性
left和top代表该元素左上角的X和Y坐标,right和bottom代表元素右下角的X和Y坐标
height和width属性老版本IE并未实现
返回的结果并不是“实时的”
4、查看元素的尺寸
dom.offsetWidth,dom.offsetHeight
5、查看元素的位置
dom.offsetLeft,dom.offsetTop
对于无定位父级的元素,返回相对文档的坐标。
对于有定位父级的元素,返回相对于最近的有定位的父级的坐标。
dom.offsetParent
返回最近的有定位的父级,如无,返回body
body.offsetParent,返回null
eg:求元素相对于文档的坐标 getElementPosition
6、让滚动条滚动
window上有三个方法
①scroll(),scrollTo() 滚动到x,y位置
window.scrollTo(x,y) === window.scroll(x,y)
②scrollBy() 滚动累加x,y
window.scrollBy(x,y)
三个方法功能类似,用法都是将x,y坐标传入,即实现让滚动轮滚动到当前位置
区别:scrollBy()会在之前的数据基础之上做累加
eg:利用scrollBy() 快速阅读的功能
脚本化CSS
1、读写元素css属性
elem.style.prop
可读写行间样式,没有兼容性问题,不能获取外部CSS样式
碰到float这样的关键字属性,前面应加css
eg:float ==> cssFloat
复合属性最好拆解
组合单词变成小驼峰式写法
写入的值必须是字符串格式
div.style.color = "red";
div.style.width = "120px";
div.style.backgroundColor = "green";
2、查询计算样式
①window.getComputedStyle(elem, null);
计算样式只读
IE8及IE8以下不兼容
返回的计算样式的值都是绝对值,没有相对单位
第二个参数可用来解决伪元素问题
window.getComputedStyle(div,null).width;
window.getComputedStyle(div,null).backgroundColor;
window.getComputedStyle(div,"after").width;
②elem.currentStyle
计算样式只读
返回的计算样式的值不是经过转换的绝对值
IE独有的属性
div.currentStyle.width;
封装兼容性方法,获取样式属性值getStyle(obj, prop);
function getStyle(elem, prop) {
if(window.getComputedStyle){
return window.getComputedStyle(elem, null)[prop];
}else{
return elem.currentStyle[prop];
}
}
事件分类
1、鼠标事件
click、mousedown、mousemove、mouseup
click = mousedown + mouseup
contextmenu(右键菜单)
mouseover(鼠标移入)、mouseout(鼠标移出)
mouseenter(鼠标移入)、mouseleave(鼠标移出)
用button来区分鼠标的按键,左键0/滚轮1/右键2
DOM3标准规定:click事件只能监听左键,只能通过mousedown和mouseup来判断鼠标键
// 如何解决mousedown和click的冲突
var firstTime = 0,
lastTime = 0,
key = false;
document.onmousedown = function () {
firstTime = new Date().getTime();
}
document.onmouseup = function () {
lastTime = new Date().getTime();
if(lastTime - firstTime < 300){
key = true;
}
}
document.onclick = function () {
if(key){
console.log('click');
key = false;
}
}
2、移动端
touchstart touchmove touchend
3、键盘事件
keydown 按键按下触发
keypress 按键按下触发
keyup 按键抬起触发
keydown > keypress > keyup
keydown和keypress的区别:
keydown 可以响应任意键盘按键,不可以检测大小写,可用来设置操作类按键
keypress 只可以相应字符类键盘按键,可以检测大小写
keypress 返回ASCII码,可以转换成相应字符
document.onkeypress = function () {
console.log('press');
}
document.onkeydown = function () {
console.log('down');
}
document.onkeyup = function () {
console.log('up');
}
4、文本操作事件
input 内容改变触发事件
focus 聚焦触发事件
blur 失焦触发事件
change 聚焦与失焦对比发生改变时触发事件
5、窗体操作类(window上的事件)
scroll 滚动条滚动时触发事件
load 等文档构建完之后执行,效率最低,不使用
json ==> {}
一种传输数据的格式(以对象为样板,本质上就是对象,但用途有区别,对象就是本地用的,json是用来传输的)
JOSN.parse(); string ==> json
JSON.stringify(); json ==> string
json对象的属性名必须加双引号 {“name” : “deng”,“age” : 123}
domTree + cssTree = randerTree
reflow 重排 dom节点的删除,添加,宽高变化,位置变化
display:none ==> block,offsetWidth,offsetLeft
repaint 重绘 字体颜色
异步加载js
1、defer异步加载
只有IE能用,代码可以写在标签内部,dom文档解析完才会执行
<script src="tools.js" defer="defer"></script>
2、async异步加载
IE9以上和其他浏览器,代码不能写在标签内部,只能加载外部脚本,加载完就执行
<script src="tools.js" aysnc="aysnc"></script>
3、创建script,插入DOM中,加载完毕后callBack
function loadScript(url, callback){
var script = document.createElement('script');
script.type = "text/javascript";
if(script.readyState){
// IE里面判断script标签加载进度,状态码
// script.readyState = "loading";加载中
// script.readyState = "complete/loaded";加载完成
script.onreadystatechange = function () {
if(script.readyState == "complete" || script.readyState == "loaded"){
callback();// 利用回调函数执行
// eval(callback); 把callback当作函数代码执行
// tools[callback](); 把方法放在对象里执行
}
}
}else{
// Safari Chrome Opera Firefox,确保异步加载完再执行后面的语句
sprict.onload = function () {
callback();// 利用回调函数执行
// eval(callback); 把callback当作函数代码执行
// tools[callback](); 把方法放在对象里执行
}
}
script.src = url;
document.head.appendChild('script');
}
// 调用时代码写法 三种:
// 利用回调函数执行
// loadScript('demo01.js', function () {
// test();
// });
// 把callback当作函数代码执行
// loadScript('demo01.js', 'test');
// 把方法放在对象里执行
// var tools = {
// test : function () {
// console.log('a');
// },
// demo : function () {
// console.log('b');
// }
// }
js加载时间线
1、创建Document对象,开始解析web页面
解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中
这个阶段document.readyState = ‘loading’
2、遇到link外部css,创建线程加载,并继续解析文档
3、遇到script外部js,并且没有设置async、defer,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档
4、遇到script外部js,并且设置有async、defer,浏览器创建线程加载,并继续解析文档
对于async属性的脚本,脚本加载完成后立即执行
异步禁止使用document.write()
5、遇到img等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档
6、当文档解析完成,document.readyState = ‘interactive’
7、文档解析完成后,所有设置有defer的脚本会按照顺序执行
注意与async的不同,但同样禁止使用documentwrite()
8、document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段
// JS里面的语法 当dom解析完就执行的部分,最好不用window.onload
document.addEventListener('DOMContentLoad', function () {
console.log('a');
}, false);
// jQuery里面的语法 当dom解析完就执行的部分
$(document).ready(function () {
});
9、当所有async的脚本加载完成并执行后、img等加载完成后,document.readyState = ‘complete’,window对象触发load事件
10、从此,以异步响应方式处理用户输入、网络事件等
正则表达式 RegExp
1、转义字符\
\n 换行
\r 行结束
\t 制表符,一个缩进
多行字符串 后面加\表示把文本回车转义掉
var test = "\
<div></div>\
<span></span>\
";
2、正则表达式的作用:匹配特殊字符或有特殊搭配原则的字符的最佳选择
3、两种创建方式
①直接量 ==> 推荐用法
var reg = /abc/;
vae str = "abcde";
reg.test(str); ==> 测试str字符串是否含有reg里的片段
str.match(reg); ==> 返回str里符合reg的片段
var reg = /abc/i; ==> 加i属性表示忽视大小写
var reg = /abc/g; ==> 加g属性表示执行全局匹配
var reg = /abc/m; ==> 加m属性表示执行多行匹配
②new RegExp();
var reg = new RegExp("abc");// 第一个参数代表规则,第二个参数代表属性m/i/g
// 以下方法构建的是两个正则表达式
var reg = /abcd/;
var reg1 = new RegExp("reg");
// 以下表示同一个正则表达式
var reg = /abcd/;
var reg1 = RegExp("reg");
4、表达式、元字符、量词
表达式 | 使用方法 |
---|---|
[abc] | 方括号内的任何字符 |
[^ab] | 除了ab字符外其他字符 |
[0-9] | 0-9任意字符 |
[a-z] | a-z任意字符 |
[A-Z] | A-Z任意字符 |
[A-z] | A-z任意字符 |
(abc|bcd) | abc或bcd |
(abc|bcd)[0-9] | abc或bcd后面加0-9任意字符 |
元字符 | 使用方法 |
---|---|
\w | [0-9A-z_] |
\W | [^\w] |
\d | [0-9] |
\D | [^\d] |
\s | [\t\n\r\v\f ] |
\S | [^\s] |
. | [^\r\n] |
\b | 单词边界 |
\B | 非单词边界 |
\n | 换行 |
\r | 回车符 |
\t | 制表符 |
\v | 垂直制表符 |
\f | 换页符 |
\uxxxx | 查找以16进制数xxxx规定的Unicode字符 |
量词 | 使用方法 |
---|---|
后面加? | 取消贪婪匹配,取1 n+?,n*? |
后面加?? | 能去0不取1 n+??,n*?? |
n+ | 包含(1 ~ +∞)个n的字符串 |
n* | 包含(0 ~ +∞)个n的字符串 |
n? | 包含(0 ~ 1)个n的字符串 |
n{X} | 包含X个n的序列的字符串 |
n{X,Y} | 包含X至Y个n的序列的字符串 |
n{X, } | 包含至少X个n的序列的字符串 |
n$ | 任何以n结尾的字符串 |
^n | 任何以n开头的字符串 |
?=n | 正向预查/正向断言,任何其后紧跟指定字符串n的字符串 |
?!n | 非正向预查/非正向断言,任何其后没有紧跟指定字符串n的字符串 |
var str = "abaaaa";
var reg = /a(?=b)/g;// 后面有b的a,b不参与选择
var reg1 = /a(?!b)/g;// 后面没有b的a,b不参与选择
// ()表示子表达式
// \1反向引用第一个()表达式里的内容
// \2反向引用第二个()表达式里的内容
var str = 'aaaa';
var reg = /(\w)\1\1\1/g;
str.match(reg);
var str1 = 'aaaabb';
var reg1 = /(\w)\1\1\1(\w)\2/g;
str1.match1(reg1);
// 检查一个字符串首位是否有数字
var reg = /^\d | \d$/g;
5、属性
global RegExp是否具有标志g
multiline RegExp是否具有标志m
ignoreCase RegExp是否具有标志i
source 正则表达式原文本
lastIndex 一个整数,表示下次匹配的字符位置,加g属性游标会移动,不加不移动
6、方法
reg.exec() 通过指定的模式搜索字符串,并返回已找到的文本,如果未找到匹配,返回null
var str = 'aabb';
var reg = /w/g;
console.log(reg.exec);
var str1 = 'aabb';
var reg1 = /(\w)\1(\w)\2/g;
console.log(reg1.exec);
支持正则表达式的string方法
str.match() 找到一个或多个正则表达式的匹配
str.search() 检索与正则表达式相匹配的位置,-1表示检测不到
str.split() 把字符串分割为字符串数组
str.tpUpperCase() 变大写
str.toLowerCase() 变小写
str.replace() 替换与正则表达式匹配的子串
var str = "aabb";
str.replace("a", "b");// 只匹配一个
var reg = /a/;
str.replace(reg, "b");// 只匹配一个
var reg1 = /a/g;
str.replace(reg1, "b");// 全局匹配
var reg2 = /(\w)\1(\w)\2/g;
str.replace(reg2, "$2$2$1$1");// str.replace里$1表示\1,$2表示\2
// 系统会帮忙自动传参
// 第一个参数 正则表达式匹配的内容
// 第二个参数 第一个子正则表达式匹配的内容
// 第三个参数 第二个子正则表达式匹配的内容
str.replace(reg2, function ($, $1, $2) {
return $2 + $2 + $1 +$1;
});
// 字符串去重
var str = "aaaaabbbbbbccccc";
var reg = /(\w)\1*/g;
console.log(str.replace(reg, "$1"));
// 字符串打点
var str = "100000000000";
var reg = /(?=(\B)(\d{3})+$)/g;
console.log(str.replace(reg, "."));
BOM window,localtion,screen,history,navigator
1、Window 对象属性
closed 返回窗口是否已被关闭
defaultStatus 设置或返回窗口状态栏中的默认文本
length 设置或返回窗口中的框架数量
location 用于窗口或框架的Location对象
name 设置或返回窗口的名称
opener 返回对创建此窗口的窗口的引用
innerheight 返回窗口的文档显示区的高度
innerwidth 返回窗口的文档显示区的宽度
outerheight 返回窗口的外部高度
outerwidth 返回窗口的外部宽度
pageXOffset 设置或返回当前页面相对于窗口显示区左上角的 X 位置
pageYOffset 设置或返回当前页面相对于窗口显示区左上角的 Y 位置
parent 返回父窗口
self 返回对当前窗口的引用,等价于Window属性
status 设置窗口状态栏的文本
top 返回最顶层的先辈窗口
window 等价于self属性,它包含了对窗口自身的引用
2、Window 对象方法
alert() 显示带有一段消息和一个确认按钮的警告框
confirm() 显示带有一段消息以及确认按钮和取消按钮的对话框
prompt() 显示可提示用户输入的对话框
print() 打印当前窗口的内容
close() 关闭浏览器窗口
open(url, name, features, replace) 打开一个新的浏览器窗口或查找一个已命名的窗口
blur() 把键盘焦点从顶层窗口移开
createPopup() 创建一个 pop-up 窗口
focus() 把键盘焦点给予一个窗口
moveBy() 可相对窗口的当前坐标把它移动指定的像素
moveTo() 把窗口的左上角移动到一个指定的坐标
resizeBy() 按照指定的像素调整窗口的大小
resizeTo() 把窗口的大小调整到指定的宽度和高度
scrollBy() 按照指定的像素值来滚动内容
scrollTo() 把内容滚动到指定的坐标
setInterval() 按照指定的周期(以毫秒计)来调用函数或计算表达式
setTimeout() 在指定的毫秒数后调用函数或计算表达式
clearInterval() 取消由setInterval()设置的timeout
clearTimeout() 取消由setTimeout()设置的timeout
3、Navigator 对象属性
appCodeName 返回浏览器的代码名
appMinorVersion 返回浏览器的次级版本
appName 返回浏览器的名称
appVersion 返回浏览器的平台和版本信息
userAgent 返回由客户机发送服务器的user-agent头部的值
userLanguage 返回OS的自然语言设置
4、Navigator 对象方法
javaEnabled() 浏览器是否启用Java
taintEnabled() 浏览器是否启用数据污点(data tainting)
5、History 对象属性
length 返回浏览器历史列表中的URL数量
6、History 对象方法
back() 加载history列表中的前一个URL
forward() 加载history列表中的下一个URL
go() 加载history列表中的某个具体页面,n向前走n页,-n向后走n页
7、Location 对象属性
hash 设置或返回从井号(#)开始的URL(锚)
host 设置或返回主机名和当前URL的端口号
hostname 设置或返回当前URL的主机名
href 设置或返回完整的URL
pathname 设置或返回当前URL的路径部分
port 设置或返回当前URL的端口号
protocol 设置或返回当前URL的协议
search 设置或返回从问号(?)开始的URL(查询部分)
8、Location 对象方法
assign() 加载新的文档
reload() 重新加载当前文档
replace() 用新的文档替换当前文档
Doctype
1、渲染模式,严格模式/怪异模式
</--!三种标准模式的写法-->
<!DOCTYPE html>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
2、label标签
<label for="demo">username:</label><input id="demo"></input>
<script>
var oInpt = document.getElementsByTagName('input');
oInpt = onclick = function () {
alert(0);
};
</script>
3、属性映射 HTML属性 映射到Element属性
系统自带属性type,id,class… ==> 特性 一一映射,可读写
4、img图片预加载
<button>click me</button>
<script>
var oBtn = document.getElementsByTagName('button')[0];
var oImg = new Image();
oImg.src = "https://pan.baidu.com/box-static/disk-theme/theme/white/img/logo@2x.png";
oImg.onload = function () {
oBtn.onclick = function () {
document.body.appendChild(oImg);
}
}
</script>
5、封装byClassName方法
Document.prototype.getByClassName = function (className){
// 类数组变成数组
var allDomArr = Array.prototype.slice.call(document.getElementsByTagName('*'), 0);
var filterDomArr = [];
function dealClass(dom) {
var reg = /\s+/g;
// trim()去掉字符串左右两边空格
var arrClassName = dom.className.replace(reg, ' ').trim().split(' ');
return arrClassName;
}
allDomArr.forEach(function (ele, index) {
var classStrArr = dealClass(ele);
for (var i = 0; i < classStrArr.length; i++) {
if (className == classStrArr[i]) {
filterDomArr.push(ele);
break;
}
}
});
return filterDomArr;
}
console.log(document.getByClassName('demo2'));
6、Math.random() 和彩票程序 0-36的随机数
Math.random() * 15 + 15;// 15-30的随机数
7、文档碎片
js 操作DOM 时发生了什么
每一次对DOM 操作都发生了 “重排”,这严重消耗性能。 一般通常的做法是减少dom 操作, 减少发生重排的做法。
什么是文档碎片?
document.createDocumentFragment(),一个容器用于暂时存放创建DOM 元素。
文档碎片有什么作用?
将需要添加的大量元素,先添加到文档文档碎片中,再将文档碎片添加到需要插入的位置, 大大大减少DOM 操作, 提高性能。
var frag = document.createDocumentFragment();
var oUl = document.getElementById('uu');
for (var i = 1000; i--; ){
var oLi = document.createElement('li');
frag.appendChild(oLi);
}
oUl.appendChild(frag);
8、cdn 缓存
用户浏览器与服务器交互,没有接入CDN时:用户在浏览网站的时候,浏览器能够在本地保存网站中的图片或者其他文件的副本,这样用户再次访问该网站的时候,浏览器就不用再下载全部的文件,减少了下载量意味着提高了页面加载的速度。
用户浏览器与服务器交互,接入CDN时:客户端浏览器先检查是否有本地缓存是否过期,如果过期,则向CDN边缘节点发起请求,CDN边缘节点会检测用户请求数据的缓存是否过期,如果没有过期,则直接响应用户请求,此时一个完成http请求结束;如果数据已经过期,那么CDN还需要向源站发出回源请求(back to the source request),来拉取最新的数据。
9、错误调试
①看错误信息
②控制台断点调试
10、区分以下
typeof(new Array).__proto__.constructor();
typeof(new Array).__proto__.constructor;