【JavaScript 笔记】基础内容

文章目录

JavaScript 特点

1、浏览器组成

​ shell + 内核【渲染引擎(语法规则和渲染)、js引擎、其他模块】

主流浏览器内核
IEtrident
Chromewebkit、blink
FirefoxGecko
Safariwebkit
Operapresto
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、nullarray、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()

数据返回值
numbernumber
stringstring
false、trueboolean
null、arrayobject
undefinedundefined
functionfunction
4、Number() 转换为数字类型
数据返回值
number本身值
true1
null、false0
undefinedNaN
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;
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值