JavaScript知识点

Day 01

 

1Javascript 概述

1、什么是Javascript (JS)

Javascript 是一种运行于 JS解释器/引擎 中的解释型脚本语言

 

JS解释器/引擎 :JS运行环境

1、独立安装的解释器 NodeJS

2、浏览器内核中嵌入的JS解释器

 

PC机,手机,平板,电视 。。。。

 

解释性脚本语言:

解释型:运行之前不会编译

编译型:运行之前先编译  C,C++ ...

2JS的发展史

11992年 , Nombas 为自己的软件写一款脚本语言 C--  --ScritEase ,可以嵌入在网页中运行

21995年 ,Netscape(网景) Navigator2.0 --> LiveScript --> Javascript ,Java Javascript之间没有任何关系

31996年 ,Microsoft IE3.0 中发布 JS的克隆版 --> JScript

41997年 ,Javascript 1.1 版本 作为 草案 提交给了  ECMA(欧洲计算机制造商联合会) ECMA-262标准  ECMAScript 作为 JS的 标准核心。 ES5  ES6

 

 

完整的JS的组成:

1、核心(ECMAScript)

2、文档对象模型(DOM,Document Object Model) , JS有能力与页面元素进行对话

3、浏览器对象模型(BOM,Browser Object Model) ,让JS有能力与网页进行对话

3JS的特点

1、编写简单 - 任何文档编辑工具都可以编辑JS

2、无需编译,直接运行

3、弱类型编程语言

   强类型编程语言: C,C++Java ...

特点:由数据类型来决定数值

 弱类型编程语言:JS

特点:由数值 来决定数据类型

4、面向对象的编程语言

4JS的用途

1、客户端的JS

1、客户端的数据计算

2、表单输入验证

3、网页中的事件触发和处理

onclick  -- 单击元素时做的操作

4、网页特效制作

5、服务器端异步数据提交(AJAX)

2、服务器端的JS

1、分布式运算

2、实时服务器

3、窗口应用

4、网络应用

2Javascript基础语法(重点)

1、浏览器内核

1、作用

负责页面内容的渲染

2、引擎

1、内容排版引擎-解析HTML/CSS

2、脚本解释引擎-解析JS

3、常用浏览器的内核和引擎

1Microsoft IE

内核:Trident

排版引擎:-

脚本引擎:Chakra

2Mozilla Firefox

内核:Gecko

排版引擎:-

脚本引擎:猴子(Monkey)系列

3Apple Safari

内核:Webkit

排版引擎:Webcore

脚本引擎:Nitro

4Google Chrome

内核:Webkit

排版引擎:Webcore

脚本引擎:V8

5Opera

内核:Presto

排版引擎:-

脚本引擎:Carakan

 

2013 以后

内核:Webkit

排版引擎:Webcore

脚本引擎: V8

2JS运行环境

1、独立安装的JS解释器(了解)

NodeJS

 

代码:

 console.log("Hello World");

 

退出 Node

Ctrl + C 2

2、嵌入在浏览器内核中的JS引擎(重点)

1、直接在Console 中输入脚本并执行

2、将脚本嵌入在HTML页面中执行

1html元素事件

onclick --> 单击时执行的操作

onmouseover

onmousemove

on....

2<script>元素中编写JS脚本

<script></script>

可以出现在网页的任何位置处

<script>

JS脚本

</script>

 

document.write("内容");

3、外部脚本文件

1、创建脚本文件并编写 脚本

脚本文件:***.js

2、引入外部脚本文件

<script src="脚本文件路径"></script>

注意:

1、必须是成对的 script

2、该对标记中,不允许出现任何内容

3JS调试

1、代码错误

解释型语言,若某行代码错误,则解释器终止此次执行

但不会影响后续块的执行,以及后续HTML解析

<script></script>

<script></script>

... ...

4、语法规范

1、代码组成

1、语句 - 能够被JS引擎所执行的代码

通常由 ; 作为结尾

表达式、关键字、运算符 来组成

console.log("");

var s=1+2;

2、注释

1、单行注释

// 单行注释

2、多行注释

/*

 *

 *

 *

 *

 */

2、严格区分大小写

console.log("");

Console.log(""); //错误

3、变量和常量(重难点)

1、变量

内存:保存程序在运行过程中所需要用到的数据(临时性)

变量:内存中的一段内存空间

值:变量中(内存空间中)所保存的数据

变量名:内存空间的别名,自定义

 

1、变量的声明

1、声明

var 变量名;

2、赋值

变量名=;

3、声明变量并赋初始值

var 变量名=;

4、注意

1、声明变量时可以不加 var 关键字

var stuname="张三丰";

==

stuname="张三丰";

 

如果省略了 var 关键字, 那么声明的就是"全局变量",有可能造成 "全局污染" 的效果

2、如果声明变量没有赋值的话,那么将自动赋值为 undefined

5、一次性声明多个变量

声明 stunamestuagestugender 变量

var stuname;

var stuage;

var stugender;

 

一次性声明多个变量 使用一个 var 关键字, 多变量名之间 用 , 分隔

var stuname, stuage,stugender;

2、变量名的规范

1、标识符

表示 变量  函数的名称

2、要求

1 、不允许使用语言的关键字和保留关键字作为标识符的名称

3、命名规范

1、可以包含字母、数字、下划线、$

var +name; //错误 ,不能有 +

2、不能以数字开头

var 1name; //错误

var name1; //正确

var $name; //正确

var _name; //正确

3、尽量见名知意

var a;

var b,c,d,e,f,g,aab,aac;

//以上方式, 不推荐

 

var username;

var salary;

4、可以采用 "匈牙利命名法","驼峰命名法","下划线命名法"

1、匈牙利命名

表单控件缩写+功能

var txtUsername= ....;

2、驼峰命名法

如果 变量名 是由多个单词组成的合成词,从第二个单词开始,每个单词的首字符变大写。

var age;

var gender;

var salary;

 

var userName;

var userSalary;

var stuJavaScore

3、下划线命名法

var _userName;//一般用于全局变量命名

var user_name;

3、变量的使用方式

1、未经初始化的变量

1、变量声明之后,从未赋过值

var userName;

console.log(userName);

结果为:undefined

2、变量未被声明而直接使用

console.log(userName);

2、变量的存取操作

1、存 - SET操作

将数据保存到 内存中的过程

var useName = "张三丰";

userName = "张翠山";

userName = "张无忌";

特点:变量名成出现在 赋值符号(=) 的左边,一律是 赋值操作

2、取 - GET操作

var userSalary = 8000; //赋值操作

console.log(userSalary);//

var newSalary = userSalary + 10;

 

特点:只要不是 赋值操作,那么就都是取值。

 

= : 如果出现 赋值符号, 先算 右边的数据的结果,再赋值给 左边的变量

var age=18;

 

18=15;//错误,=的左边必须是变量

 

3、练习

套餐名称:

香辣鸡腿堡

汉堡名称:

香辣鸡腿煲

配餐名称:

烤翅

饮料名称:

可口可乐

2、运算符

1、算术运算符

+,-,*,/,%

% : , 获取两个数字的余数

5 % 2  ==> 5 / 2 = 2 ... 1

 

ex

1、判断 5 是否为 偶数

2、获取  1234 的最后 一位数

/ : 除法

* : 乘法

- : 减法

+ :

1、两个 数字 做 + ,就是 求和

var num1=15;

var num2=18;

var result=num1+num2;//33

2、如果+两边有一个不是数字的话,那么就 做 字符串的累加

var s1="你好";

var s2="世界";

var result=s1+s2;//你好世界

 

*****************

var num1 = 18;

var num2 = "15";

var result=num1+num2;

// 33

// 1815

2、算术运算符的优先级

1、正常 从左向右 运算

2、先 */% +-

var result = 25+4*8/2+6%3;

 

25+16+6%3;

25+16+0

41

 

 

var result = "你好"+13+25;

结果为:

你好1325

 

var result = 13+25+"你好";

结果为:

38你好

3、提升优先级

var result = 25+4*8/2+6%3;

使用 () 提升优先级

var result = (25+4)*8/((2+6)%3);

== 29*8/(8%3) == 29*8/2 = 116

3、常量

1、什么是常量

一旦声明好,就不能被修改的数据 叫做常量

 

π = 3.14

hourOfDay=24

2、声明常量

const 常量名=;

注意:常量声明时,必须赋值

常量的名称 一般采用 全大写 方式

ex:

const PI=3.14;

3、练习

程序中,声明一个变量(r),表示圆的半径,并且赋值,计算 该圆的周长(l),和面积(s)

l = 2*π*r;

s = π*r*r;

 

半径为10的圆的周长为62.8

半径为10的圆的面积为314

4、数据类型

1、什么是数据类型

保存在内存的数据的类型 是什么

8bit() = 1byte(字节)

1024byte = 1kb(千字节)

1024kb = 1MB

1024MB = 1GB

1024GB = 1TB

2、数据类型分类

1、基本数据类型(原始类型)

1number 类型

数字类型

表示 32位的整数 也可以表示64位的浮点数

 

整数:

1、十进制

var num = 125;

2、八进制

var num = 0125;

3、十六进制

var num = 0x123AF

小数

1、小数点

var num = 123.456;

2、指数记录

var num = 5.6e10;

2string 类型

字符串类型

表示 一系列的文本字符的数据

Unicode 字符、数字、标点来组成

汉字的范围:

\u4E00 ~ \u9FA5

 

必须使用  "" '' 引起来数据

var n = 15;//number 类型

var n1 = "15";//string 类型

 

转义字符

\n : 换行

\r : 回车

\t : 制表符

\" : "

\' : '

\\ : \

3boolean 类型

布尔类型

仅有两个值:true false

 

var result = true; //

var result = false; //

 

var result = "false"; //string 类型

 

做算术运算时,true = 1false=0

var num = 45;

console.log(num+true);//46

4undefined 类型

语义:不存在该数据

场合:

1、声明变量未赋值

2、对象属性不存在

2、引用类型

 

*******************************************************************************

Day 02

 

1、数据类型转换

1、隐式转换

var num;

num = 15; //number类型

num = "你好!";//string类型

弱类型:是由值来决定数据类型

 

var num1 = 15;

var num2 = 30;

var result = num1 + num2;

===============================

var str1 = "Hello";

var num1 = 30;

var result = str1 + num1;//Hello30

 

1typeof 函数/运算符

语法

var r1 = typeof 变量;

var r2 = typeof(变量);

2NaN

Not a Number :不是一个数字

isNaN() : 是不是一个数字

返回结果:true false

true :不是一个数字

false :是一个数字

3、结论

1、数字 + 字符串 :将数字转换为字符串

2、数字 + boolean :将 boolean 转换为 number类型

3、数字 + undefined :结果为 NaNNaN的类型为 number

4、字符串 + boolean :将boolean 转换为 字符串

5boolean + boolean :都转换成number在做相加运算

 

 

 

 

不同类型的数据在计算过程中会进行"自动转换"

2、转换函数

显示转换/强制转换

1toString()

将任意类型的数据转换为字符串类型

var newVar=变量.toString()

2parseInt()

作用:将一个数据转换成"整数"

语法:var result=parseInt(变量);

注意:

1、碰到第一个非数字字符则停止转换,已经转换的则保留

2、如果第一个字符就是非数字字符,结果为 NaN

3parseFloat()

作用:将指定的数据转换为 小数

语法:var result = parseFloat(变量);

4Number()

作用:将一个数据转换为 number 类型

注意:

只要包含非法字符(除数字和小数点),则返回NaN

3、练习

console.log("");//控制台打印

document.write("");//页面输出

window.alert();/alert();//页面弹框

 

输入:

window.prompt();/prompt();//页面输入框

 

prompt("提示文本");

2、运算符和表达式

1、分类

1、单目运算符

只需要一个操作数即可

2、双目运算符

需要两个操作数的的运算符

a + b;

5 % 2;

a >= 25

3、三目运算符

需要三个操作数的运算符

?:

2、详解

1、算术运算符

+,-,*,/,%

10 % 3 : 1

10.5 % 3 :1.5

...

 

++,-- 运算符,单目运算符

 

++:自增运算,增量为1

var i=5;

i++;i=i+1;

++i;i=i+1;

 

++在后 :先使用变量的值,再对变量进行自增

var i=5;

console.log(i++);//先打印i的值,打印完成后,i再增加

 

++在前 :先对变量进行自增操作,然后再使用变量的值

var i=5;

//1、先将i的值自增(+1)

//2、打印i的值 6

console.log(++i);

 

--:自减运算,减量为1

变量--; //先使用 变量值,然后再自减

--变量; //先自减,然后再使用变量值

 

四舍五入:toFixed(保留位数);

语法:数字.toFixed(n);

 

由算术运算符所组成的表达式,称之为 算术表达式

var a;

var b;

var c = a + b; //算术表达式,赋值表达式

2、关系运算符

1、作用

判断数据之间的大小或相等关系

2、关系运算符

>,<,>=,<=,==,!=

关系运算符所组成的表达式 称之为 关系表达式,关系表达式的值为boolean类型

 

==!= : 只判断数值是否相等,与类型无关

 

全等:===

类型相同

数值相同

不全等:!==

3isNaN函数

1、作用

判断其参数是否为一个 "非数字"

 

返回值:

true :值不是一个数字

false:值是一个数字

4、逻辑运算符

1、作用

判断多条件 以及 条件取反时使用

2、语法

1、逻辑 非

对现有条件 取反

语法:!

2、逻辑 与

两个条件,两条件同时为真时,&& 表达式才为真。

语法:&&

ex

考试通过条件:

1、机试 >= 60

2、笔试 >= 60

3、逻辑 或

两个条件,只要有一个为真时,表达式即为真

语法:||

3、运算结果

true && true : true

true && false : false

false && true : false

false && false :false

 

true || true : true

true || false :true

false || true : true

false || false :false

 

练习:输入一个数字,判断该数字是否在 0 ~ 10 之间

 

练习:判断字符

中文 : \u4e00  ~ \u9FA5

英文 'a'~'z' 或者 'A'~'Z'

数字 '0'~'9'

 

闰年:

1、年份能被4整除但是不能被100整除是闰年

2、年份能够 400 整除 也是闰年

4"短路逻辑"

对于 && : false && ? : false

如果第一个表达式已经为假的话,那么第二个表达式就不需要再判断,并且将第一个表达式的值 作为 整个逻辑表达式的值。

对于 || : true || ? :true

如果第一个表达式已经为真的话,那么第二个表达式就不需要再判断

 

当做假看待的 数值:

"" : 空字符串

0 :

0.0

undefined :

NaN

null:

5、位运算符

1、二进制

0,1组成,逢二进一

二进制        十进制

0             0

1             1

10            2

11            3

100           4

 

内存中:

4在内存中的形式:

0000 0000 0000 0000

0000 0000 0000 0100

 

1在内存中的形式

0000 0000 0000 0000

0000 0000 0000 0001

2、按位 与

语法:&

作用:将两边得到操作数都转换成二进制,每位上的数字,只有都为1的时候,该位的结果才为 1,否则 该位按0处理

ex : 1 & 3

1 : 01

3 : 11

r : 01

 

5 & 3

5 : 101

3 : 011

r : 001

场合:判断一个数字的奇偶性。n&1,结果为1n为奇数,否则n为偶数

 

5 & 1

5 101

1 001

r 001

 

6 & 1

6 : 110

1 : 001

r : 000

3、按位

: |

: ~

4、按位异或 : ^

语法:^

作用:两个数的二进制中,该位数字只有一个1的时候,该位结果才为1,其他情况都是0

ex:

5 ^ 3

5 : 101

3 : 011

r : 110

使用场合:互换两个数字时,不借助第三方变量时使用 异或

var num1=1,num2=2;

 

var temp = num1;

num1 = num2;

num2 = temp;

*******************

num1=num1^num2;

num2=num2^num1;

num1=num1^num2;

****************************

num1=5,num2=3;

 

num1 : 101

num2 : 011

 

num1=num1 ^ num2

num1 : 101

num2 : 011

num1=  110   = 6

 

num2=num2 ^ num1;

num2 : 011

num1 : 110

num2=  101   = 5

 

num1=num1 ^ num2;

num1 : 110

num2 : 101

num1=  011   = 3

5、左移

语法:<<

作用:将 对应的二进制数,向左移动几位,后面以 0 补齐位置

2<<1

 

2:10

 

0000 0000 0000 0000

0000 0000 0000 1000

2<<1 : 100  = 4

2<<2 : 1000 = 8

2<<3 : 10000=16

2<<4 : 100000=32

 

6、右移

语法:>>

作用:将 对应的二进制数,向右移动几位,前面以 0 补齐位置

2>>2 :

0000 0000 0000 0000

0000 0000 0000 1000

6、条件运算符(三目运算符)

1、语法

? :

表达式1?表达式2:表达式3;

表达式1,值应该为 boolean 类型

 

如果表达式1的值为true,那么表达式2的值则作为整个表达式的值

 

如果表达式1的值为false,那么表达式3的值则作为整个表达式的值

 

ex :输入考试成绩,如果成绩大于等于60 ,则输出及格,否则输出 不及格

 

*******************************************************************************

Day 03

 

1、赋值运算符

1=

变量 = 表达式|数值;

 

var salary = 2000;

var result = salary >= 5000;

 

var a=b=c=10; //可以,不推荐该写法

2、扩展赋值表达式

+=,-=,*=,/=,%=,^=

 

声明一个变量salary表示工资,并赋值为1000,为salary+500,作为涨工资后的结果,打印工资

1

var salary = 1000;

var newSalary = salary + 500;

2

var salary = 1000;

salary = salary + 500;

3、语法

a += b; ==> a = a + b;

a *= b; ==> a = a * b;

4、练习

a=18

b=25

 

a=25b=18

2、函数(重难点)

1、什么函数

函数:function,也叫 方法(method)或过程(procedure)

 

是一段预定义好,并且可以被反复执行的代码块。

预定义:提前先声明好,不是马上使用。

反复执行:可以被循环利用

代码块:允许包含多条可执行语句

 

函数本质实际上是功能完整的对象。

2、定义 函数(方法)

1、语法

function 函数名(){

若干可执行语句(代码块)

}

 

函数名:遵循标识符的规范

2、函数调用

允许出现JS脚本的地方都可以实现 "函数调用"

语法:函数名();

 

parseInt();

parseFloat();

Number();

console.log();

3定义带参函数(定义的时候传进去的是行参

1、语法

function 函数(参数列表){

代码块

}

参数列表:由一个或多个 参数名称 组成,多个参数间,用 , 来 分隔。定义时的参数,称之为 "形参(形式上的参数)"

2、调用(调用的时候传进去的是实参

函数名(参数列表);

参数列表:由一个或多个 组成,按照定义好的顺序,往里传递。调用函数时所传递的参数值,称之为 "实参(实际参数)"

 

function parseInt(value){

.......

}

4带返回值的函数

var num=parseInt("25.5");

 

语法:

function 函数名([参数列表]){

代码块;

//如果有返回值

return /表达式;

}

 

return:返回

1、将指定的值或表达式带出到函数调用的位置处

2、并终止当前函数的执行

 

5、练习

1、定义一个可以接受两个数字的方法,返回这两个数字的和,并调用方法,打印输出最终结果

3、变量的作用域

1、什么是作用域

作用域就是变量或函数的可访问范围。控制变量或函数的可见性和生命周期

 

作用域可分为:

1、函数作用域:局部变量(函数),只能在当前函数内访问

2、全局作用域:全局变量(函数),一经定义,代码的任何位置都能访问

2、函数作用域的变量

变量 函数 声明在某函数内,有效范围就在该函数中,出了该函数,变量 函数 就失效

3、全局作用域的变量

变量定义在 独立于 任何 function 的位置处(<script>),在代码的任何位置都可以访问到

1、独立于任何 function 声明变量

2、函数中,通过不写var的方式声明全局变量

4、注意

1、全局变量和局部变量冲突时,优先使用的是 局部变量

5、声明提前

JS程序在正式执行前,会将所有的var声明变量和function的声明函数,预读到所在作用域的顶部。

 

但是,对变量的赋值依然保留在原位置上。

6、按值传递

基本数据类型 在做参数传递时,实际上将数据进行复制 得到一个副本,将副本传递到函数参数中

4、函数作用域

1、分类

与变量相似,分为

1、全局作用域(全局函数)

2、函数作用域(局部函数)

2、常用全局函数

1parseInt()

2parseFloat()

...

3encodeURI()

uri:Uniform Resource Identifier(统一资源标识符)

作用:对统一资源标识符进行编码,并且返回 编码后的URI字符串

针对 URI 中 非 ASCII码的字符进行编码,转换为16进制的转义字符

ASCII : American Standard Code for Information Interchange

4decodeURI()

作用:对已编码的URI进行解码,返回解码后的数据

5eval()

作用:计算并执行以字符串表示的JS代码

3、分支结构(重点)

1、程序的流程控制

程序 = 数据 + 算法

 

任何复杂程序都可以通过以下三种结构实现

1、顺序结构

将可执行代码自顶向下执

2、选择结构(分支)

根据条件 选择某一块代码去执行

3、循环结构

根据条件 选择某一块代码反复执行

 

问题:当 总价 大于或等于 500时,享受8折优惠

 

分支结构:

可根据条件,选择执行某些语句

 

1、当条件满足时,运行某些语句

 当条件不满足时,则不运行这些语句

 ----if结构

2、当条件满足时,运行某些语句

 当条件不满足时,运行另外一些语句

 ----if - else 结构

2if 结构

1、语法

if(条件){

满足条件要执行的语句块;

}

流程:

1、判断 条件的值 :

如果为 true, 则执行if语句块中的语句

如果为 false,则不执行if语句块中的语句

2、注意

1、条件 是 boolean

如果 出现的 条件 不是 boolean,则会自动转换

出现以下几种情况,都作为假处理:

if(0){}

if(0.0){}

if(undefined){}

if(NaN){}

if(null){}

if(""){}

 

if("我帅吗"){

console.log("恭喜你,答对了!");

}

2、可以省略 if 后面的 {}

如果 省略 {} ,那么if 只控制它下面的第一条语句

3、问题

异常情况:如果 收款金额 小于 应收金额

3if ... else 结构

1、语法

if(条件){

满足条件所执行的代码块(语句块1)

}else{

不满足条件时所执行的代码块(语句块2)

}

 

流程:

1、判断 条件

如果值为true,则执行语句块1

如果值为false,则执行语句块2

4、成绩计算 程序

手动输入一个考试分数 (0~100)

如果成绩 100分 ,奖励一台兰博基尼

如果成绩 大于等于90分,奖励一台 法拉利

如果成绩 大于等于80分,奖励一台 奥迪Q7

如果成绩 大于等于70分,奖励一台 奥拓R8

如果成绩 大于等于60分,奖励一台 自行车

否则 奖励 俩大嘴巴子

4else  .... if 结构 (多重if结构)

1、语法

 

if(条件1){

语句块1;

}else if(条件2){

语句块2;

}else if(条件3){

语句块3;

}...else if(条件n){

语句块n;

}else{

else 语句块;

}

 

练习:

1、可莱托指数,通过 选择 结构完成

2、日期计算器

输入 出生的 年,月,日,计算 生日那一天,是那一年的第多少天!!

 

*******************************************************************************

Day 04

 

1、分支结构-2

1、条件判断

1、各种 if 结构 (ifif...else...else...if)

2、短路逻辑 条件 && 操作

3、条件运算符 :条件?满足 :不满足;

-- if(){} else{}

 

2、做等值判断的 分支 结构

1switch-case 结构

语法:

switch(变量/表达式){

case 1:

语句块1;

break; //可选

case 2:

语句块2;

break; //可选

... ...

default: //以上任何一块都没匹配上的时候

语句块n;

break; //可选

}

 

// 直落形式 : 多个 case 执行相同的语句块。

switch(变量/表达式){

case 1:

case 2:

case n:

语句块;

break;

....

}

2、循环结构-1

1、问题

1、控制台中输出 一句 Hello World

2、控制台中输出 10Hello World

3、控制台中输出 1000Hello World

4、控制台中,将 1000Hello World 变成 你好 世界!

5、控制台中,将1000句 你好 世界 的前面加上

1 句 你好世界

2 句 你好世界

1000 句 你好世界

2、循环

1、什么是循环

一遍又一遍的反复执行相同的操作!

 

生活循环:

1、跑圈 - 1、重复跑 2、圈数限制(12,25)

2、上学 - 1、重复学习过程 24个月 时间限制

3、地球公转自转 - 1、重复转 2、限制

特点:

1、循环操作 :循环体,要重复做的事情是什么

2、循环条件 :重复执行的次数,或继续执行循环的条件

2while 循环

1、语法

while(循环条件){

//循环操作

}

 

语义:当 循环条件 为真时,执行循环操作

流程:

1、判断 循环条件 (boolean表达式或值)

2、如果 结果为 真

2.1 执行循环操作

2.2 再回到条件判断位置处,继续判断条件

3、如果条件为 假

结束循环

3、循环流程控制-break

1、作用

提前 结束 循环

 

ex : 要求用户 循环的 从网页输入内容,打印在控制台上,直到 输入 exit 为止

循环条件:死循环,输入 exit 则退出循环

循环操作:

1、输入数据

2、判断 如果为 exit , 则 退出 循环

3、打印输出在控制台上

2、循环和switch 中的 break

while(true){

var n = prompt();

switch(n){

case "1":

console.log(1);

break;

case "2":

console.log(2);

break;

}

}

3、每日一练

猴子吃桃:

猴子第一天摘下若干个桃子,当即吃了一半,还不爽,又多吃了一个

第二天 ,将剩下的桃子吃了一半,又多吃一个

...

以后每天早上都吃了前一天的剩下的一半零一个

第十天 ,只剩下一个桃子了

求:第一天共摘了多少桃子

 

*******************************************************************************

 

 

Day 05

 

 

回顾:

1、分支结构 - switch

1、场合

等值判断

2、语法

switch(变量/表达式){

case 1:

语句块;

break;

......

default:

语句块;

break;

}

 

1default

任何case 都没被匹配上要执行的操作

可有可无

2、结束 switch...case运行

1break

2、走到switch结束

 

switch(n){

case 1:

console.log("1");

case 2:

console.log("2");

}

2、循环结构 - while

1、循环特点

1、循环操作 :重复做的事情是什么!

2、循环条件 :控制循环的开始与结束!

2while

2、语法

while(条件){

操作

}

 

流程:

先判断条件

如果条件为真,则执行操作,然后再判断条件 ... ...

如果条件为假,则退出循环结构

3、循环流程控制 - break

碰到 break 则提前结束循环

练习:猴子吃桃

一半零一个

10天 剩1

 

10天     剩1    x/2-1=1  x : 4 (09天的量)

09天     剩4    x/2-1=4  x : 10(08天的量)  

08天     剩10   x/2-1=10 x : 22(07天的量)

07天     剩x

... ...

02天     剩left x/2-1=left : x ? 第一天的总量

01天     剩x    

 

循环条件:9次 从10开始,到2结束

循环操作:

left : 1  - 10天所剩的桃子数量

total: ? - 第一天所剩的桃子总数

公式:total/2-1=left

  total/2 = left+1

total = (left+1)*2

 

total = (left+1)*2;

left=total;

 

输入 判断 ,该日是概念的第多少天,用循环来做

提示:月份,是循环判断的!

 

循环

1do...while 循环

1、问题

要求用户从网页中输入文本,在控制台上打印输出,直到输入 exit 为止

 

方式1:

while(true){

//输入数据

//判断是否为 exit,不是exit 打印输出

}

 

方式2:

var input="";

while((input=prompt("input")) != "exit"){

//打印

}

2、特点

执行 循环体

判断 条件

3、语法

do{

循环操作;

}while(循环条件);

4while do...while 的区别

1while 循环

先判断,再执行

最少 循环体 一次都不被执行

2do...while 循环

先执行,再判断

任何情况下,至少都要执行一次循环体

 

两种循环只在第一次执行时有差别,其他情况,whiledo...while 是完全一致。

5、练习

while 版的 猜数字 游戏,改版成 do...while

1、条件

1、用户输入的数字与生成的随机数一样(结束)

2、用户输入的exit(结束)

2、操作

1、循环录入数据

2、判断(exit?大了?小了?相等)

2for 循环

1while

通过 while 打印 1-100 之间所有的数字

条件:从1 开始 到 100结束

操作:打印 循环变量

 

var i=1;//循环条件 起始数值(表达式1)

while(i<=100){ //条件判断(表达式2)

console.log(i); //循环操作(循环操作)

i++;//更新循环变量(表达式3)

}

特点:固定循环次数

2for 循环

1、特点

while 循环中的 几个重要因素放在一起来声明,通过一个大的完整的表达式来声明 循环所需要用到的东西

2、语法

for(表达式1;表达式2;表达式3){

循环操作!

}

表达式1:循环变量的声明表达式.

表达式2:循环条件判断,条件为真,执行循环体,否则退出循环。

表达式3:更新循环变量

 

流程:

1、计算表达式1的值

2、计算表达式2的值(boolean),如果条件为真,则执行循环体,否则 退出

3、执行循环体

4、计算表达式3的值

 

5、计算表达式2的值(boolean),如果条件为真,则执行循环体,否则 退出

6、同3

7、同4

3、场合

一般用于 固定循环次数时 使用

3for语句三个表达式的特殊用法

1、表达式1允许为空

允许在循环外,将第一个表达式不足

2、表达式2允许为空

死循环

尽量不要为空,如果为空的话,尽量在循环内部将条件补充完整额。

3、表达式3允许为空

死循环

循环 内部 将表达式补充完整。

4、表达式1 和 表达式3 内容多样化

表达式1 可以一次声明多个变量

表达式3 可以一次改变多个变量的数值

多个表达式之间 , 分开

4、循环流程控制

1break

可以提前终止循环的执行

能用在循环结构中,也可以用在switch结构中

2continue

1、只能用于循环中

2、作用

跳过本次循环中的剩余语句,而继续执行下次循环

3、三种循环的使用场合

1、确定循环次数的时候 优先使用 for循环

2、不确定循环次数的时候,优先使用whiledo..while

1、先判断条件,再决定是否走循环体:while

2、先走循环体,再根据条件判断是否执行下次循环:do...while

4、循环嵌套

在一个循环中 又嵌入了另外一个循环

for(var i=1;i<=10;i++){

for(var j=1;j<=10;j++){

console.log("Hello World");

}

}

 

 

1*1=1

1*2=2 2*2=4

1*3=3 2*3=6 3*3*=9

......

1*5=5 2*5=10 3*5=15 4*5=20 5*5=25

1,2,3,4,5 : 循环条件

操作:循环条件 打印行数相乘 计算结果

 

 

1,1,2,3,5,8,13,21,34,55.....

n1 = 1,n2 = 1

 

console.log(n1);console.log(n2);// 1,1

n1=n1+n2;

n2=n1+n2;

 

console.log(n1);console.log(n2);// 2,3

n1=n1+n2;

n2=n1+n2;

 

 

f(n) : n 个月 兔子总量

f(n) = f(n-1)+f(n-2)

f(5) = f(4)+f(3)

 

f(4) : 3

f(3) : 2

f(2) : 1

f(1) : 1

 

 

 

*        11

**       22

***      33

****     44

*****    55

 

 

 

    *   11个星  第14个空格  5-1=4

   **   22个星  第23个空格  5-2=3

  ***   33个星  第32个空格  5-3=2

 ****   44个星  第41个空格  5-4=1

*****   55个星  第50个空格  5-5=0

j : 行数

k : 空格 k<=(5-j)

i : 星星 i<=j

 

 

 

    *       11个星  第14个空格

   ***      23个星  第23个空格

  *****     35个星  第32个空格

 *******    47个星  第41个空格

*********   59个星  第50个空格

 

 

Day 06

 

张东

zhangdong@tedu.cn

 

犀牛书

微信公众号: 前端大全

js1k

 

正课:

1. ***数组:

  什么是:内存中,连续存储多个数据的存储空间,再起一个名字

         一组变量的集合

  为什么:现实中存储多个相关数据,都是集中存储,共用同一个名字。

    程序=数据结构+算法

      好的数据结构可以极大的提高程序的执行效率

  何时:今后只要连续存储多个相关的数据都要用数组

  如何使用:

   创建数组: 3:

    1.创建空数组: 2:

      1.数组直接量: var arr=[];

      2.new: var arr=new Array();

    2.创建数组同时,初始化数组的数据:

      1.数组直接量: var arr=[1,2,...]

      2.new:

        var arr=new Array(1,2,...);

      3. 创建n个空元素的空数组:

        只能用new: var arr=new Array(n);

   访问数组中的元素:

    下标: 数组中唯一标识一个元素存储位置的序号

      默认从0开始,连续递增,不重复

      arr[i]: 访问下标为i位置的元素

   数组中,每个元素的用法和普通变量完全一样。

 

   数组的length属性:

     标识了数组中理论上的元素个数

     任何情况下: length永远是最大下标+1

     固定套路:

      1.最后一个元素: arr[arr.length-1]

      2.倒数第n个元素: arr[arr.length-n]

      3.追加新元素:arr[arr.length]=新值;

      4.缩容: arr.length--;

  

   特殊情况: js中的数组:3个不限制

    1. 不限制元素的数据类型

    2. 不限制下标越界

      获取元素值:

        下标越界: 不报错,返回undefined

    3. 不限制元素的个数

      设置元素值:

        下标越界:

          自动在指定位置添加新元素

          自动修改length为最大下标+1

     稀疏数组: 下标不连续的数组

 

   遍历数组: 依次访问数组中每个元素

    for(var i=0;i<arr.length;i++){

       arr[i]//当前元素

    }

  

  数组是引用类型的对象:

 

  

       

 

正课:

1. ***数组

  垃圾回收

  关联数组

  数组API

 

垃圾回收: 定期回收不再被任何变量引用的对象。释放内存。

  1. 垃圾回收器:

    伴随主程序,并行运行的一个小程序

    定期回收内存中的不再被任何变量引用的对象。

  2. 引用计数器:

    每个对象上,标记正在引用对象的变量个数的一个属性

   每多一个变量引用对象,计数器就+1

   如果一个变量通过赋值为null释放对对象的引用,则计数器-1

   直到计数器为0,表示不再有任何变量引用该对象,则该对象被回收/释放

   建议: 如果使用完较大的对象,都要主动赋值为null

 

索引数组: 下标为数字的数组

关联数组:

  什么是:可自定义下标名称的数组

  为什么:普通的索引数组的下标都是无意义的数字。不便于快速查找元素。也容易出现歧义.

    [林心如, 81, 53, 86]

      name  math chs eng

  何时:希望每个元素有专门的名称时

       通常用于快速定位元素

  如何使用:

    创建: 2:

     1.创建空数组: var lxr=[];

     2.向空数组中添加新元素:

        使用自定义的字符串元素名作为下标

       lxr["name"]="林心如";

       lxr["math"]=81;

       lxr["chs"]=53;

       lxr["eng"]=86;

    访问元素:

       lxr["name"]

    强调: 关联数组的length失效

    遍历: 不能用for循环

      for in循环:

        其中in,表示依次取出数组中每个下标

      for(var key in hash){

key//每个元素的下标名称

        hash[key]//当前元素值

      }

  关联/hash数组原理:

   hash算法: 接收一个字符串,并计算出一个尽量不重复的序号

    相同的字符串,计算出的号总是一样的

    不同的字符串,计算出的号大多数不重复

   存入数据:

      hash算法接收一个字符串的下标名,计算出一个不重复的序号。将数据存储在序号对应的数组位置上

   获取数据:

      将下标名称交给hash算法,算出和存入时完全相同的序号,直接去序号位置查找元素

    优点: 查找极快!

      和数组中元素个数,以及元素在数组中的位置无关。

 

数组API:

对象: 集中存储多个数据的一块存储空间

      并提供了操作数据的API

函数: 不属于任何对象的函数

方法: 必须用对象才能调动的函数,叫方法

 

1. 转字符串: 2

  1. 将数组中每个元素都转为字符串,再用逗号分隔: var str=String(arr);

  2. 将数组中每个元素都转为字符串,再用自定义下标连接每个元素:

var str=arr.join("自定义连接符")

     强调:如果省略参数,默认等效于String

   固定套路:

    1. 无缝拼接: arr.join("")

    2. 将单词拼接为句子: arr.join(" ")

    3. 判断空数组: arr.join("")==""

    4. 根据数组中的元素,动态生成页面元素的内容

 

2. 拼接和截取:

  拼接:

  var newArr=

      arr1.concat(1,2,arr2,....)

   将值1,2,以及arr2中每个元素依次拼接到arr1结尾,返回新数组。

   何时使用: 将多个元素或其他数组,拼接到当前数组上时

  强调:

   1.concat无权修改原数组,只能返回新数组

     所以,必须用变量接住拼接后的返回值

   2.concat可打散数组类型的参数为单个元素

 

  截取:(复制)

  var subArr=arr.slice(starti,endi+1);

   复制arrstarti位置开始到endi结束的元素组成子数组返回。

  何时: 选取数组中指定位置的子数组时

  强调: 1. 无权修改原数组,只返回新子数组

       2.含头不含尾

       3.其实可使用负数参数,表示倒数第n

  简写:

    1. 省略第二个参数,表示一直截取到结尾

    2. 两个都省略,表示完整复制原数组中的元素到新数组。

      不能只省略第一个参数——报错

3.splice: 删除,插入,替换

  删除数组中指定位置的元素:

  arr.splice(starti,n):

     删除arrstarti位置开始的n个元素

  其实: var deletes=arr.splice(starti,n)

    deletes: 返回的被删除的元素组成的临时子数组。

 

  在数组指定位置插入新元素:

  arr.splice(starti,0,1,2,...)

    starti位置插入新值

    starti位置的值被向后顺移

   强调: splice,不支持打散数组参数

  插入: splice vs concat

    concat只能在开头或结尾拼接,不能中间插入。但可打散数组类型参数

    splice可在任意位置插入,但不可打散数组类型参数。

 

  替换数组中指定位置的元素

  arr.splice(starti,n,1,2,...)

    先删除starti位置的n个旧元素

    再在starti位置插入新值

   强调: 删除的个数和插入的个数不必一致

        splice可自动调节数组的长度和位置

 

翻转: arr.reverse();

 

 

Day 07

 

回顾:

数组:

  创建:

    1. 创建空数组:

      1. 直接量: var arr=[];

      2. new: var arr=new Array();

    2. 创建数组同时,初始化数组元素:

      1. 直接量: var arr=[1,2,...]

      2. new:

var arr=new Array(1,2,...);

    3. 创建n个空元素的数组:

      new: var arr=new Array(n);

 

  访问元素:

    arr[i]

  三个不限制:

    1. 不限制元素的数据类型

    2. 不限制元素个数——添加元素时

      不报错, 在任意位置添加新元素

    3. 不限制下标越界——获取元素时

      不报错,返回undefined

 

  length: 标识理论上的元素个数

    固定套路:

      1. 最后一个: arr[arr.length-1]

      2. 倒数第n: arr[arr.length-n]

      3. 末尾追加: arr[arr.length]=

      4. 缩容: arr.length-=n;

 

  遍历: for(var i=0;i<arr.length;i++){

   arr[i]//当前元素

        }

  

  索引数组: 下标是数字的数组

    稀疏数组: 下标不连续的数组

  关联/hash数组: 可自定义下标名称的数组

    创建: 2:

      Step1: 创建空数组:

         var lxr=[];

      Step2: 向空数组中添加新元素,使用自定义的下标名称

         lxr["name"]="林心如"

 

    访问元素:lxr["name"]

 

    length属性: 失效,始终为0

    

    遍历: for(var key in hash){

            key//依次获得hash中每个下标名称

            hash[key]//当前元素

          }

 

数组API:

1. 转字符串:2

  1. var str=String(arr)

  2. var str=arr.join("自定义分隔符")

    固定套路:

     1. 无缝拼接: arr.join("")

     2. 将单词拼接为句子: arr.join(" ")

     3. 判断是否空数组: arr.join("")==""

     4. 将数组内容动态生成页面元素:

      <标签>+

      arr.join("</标签><标签>")

      +</标签>

2.拼接和选取:

  拼接:

  var newArr=arr1.concat(1,2,arr2,..)

    强调: 可打散数组参数为单个元素

  选取:

  var subArr=arr.slice(starti,endi+1)

    强调: 含头不含尾

          支持负数(倒数)下标

            其实,arr.length-n

    简写: 省略第二个参数,一直选取到结尾

          两个参数都省略, 完整复制原数组

3. splice:

   删除: var deletes=arr.splice(starti,n)

     强调: 直接修改原数组

           返回被删除的元素组成的临时数组

   插入: arr.splice(starti,0,1,2,...)

     强调: 不能打散数组类型参数

   替换: arr.splice(starti,n,1,2,...)

     强调: 插入的新元素个数不必和删除的元素个数一致。

 

4. 翻转: arr.reverse();

 

正课:

1. ***数组:

  ****排序

  栈和队列

  二维数组

2. ***String:

  

****排序:

  自定义排序算法: 冒泡,插入,快速

  冒泡: 从头开始遍历数组中每个元素

          如果当前元素>下一个元素

            就交换两数的位置

 

    交换两变量值:a,b

      1. 声明第三个变量:

         var t=a;

         a=b;

         b=t;

      2. 不声明第三个变量: 仅能交换数字

         a+=b; b=a-b; a-=b;

      3. 不声明第三个变量: 万能

         b=[a,a=b][0];

 

  使用排序API:

  arr.sort(); 默认,仅能对字符串升序排列

  解决: 自定义比较器函数

    什么是比较器函数:

        专门用来比较任意两数大小的函数

      要求:

        1. 2个参数,a,b

        2. 如果a>b,就返回正数      

           如果a<b,就返回负数

           如果a==b,就返回0

      最简单的数字比较器:

        function cmp(a,b){return a-b;}

    如何使用比较器函数:

    将比较器函数对象,作为sort方法的参数

        arr.sort(cmp);

      强调: cmp后,不要加()

           区别: 不加(),是将函数对象放入sort中,sort可反复调用执行。

                 (),仅是将函数的执行结果,放入sort中,sort方法无法反复调用。

 

  降序排列: 颠倒比较器返回值的正负

    比如:

     function cmp(a,b){return -(a-b)};

 

栈和队列:

  js中没有专门的栈和队列类型,都是用普通该数组模拟的。

  何时: 只要希望按照顺序使用数组元素时

  

  : 一端封闭,只能从另一端进出的数组

   顺序: FILO

    何时: 如果希望始终操作最后进入数组的最新的元素时。

    如何:

      结尾出入栈:

        : arr.push();

        : var last=arr.pop();

        : 每次出入栈不影响其余元素的位置

      开头出入栈:

        : arr.unshift();

        : var first=arr.shift();

        : 每次出入栈都会影响每个元素的位置

 

  队列: 只能从一端进入,从另一端出

    顺序: FIFO

    何时: 只要按照先来后到的顺序使用元素

    如何:

      从结尾入队列: arr.push()

      从开头出队列: var first=arr.shift()

 

 

正课:

1.二维数组

2.***String

 

1. 二维数组:

  什么是: 数组中的元素,又引用了另一个子数组。

  何时:

    1. 存储横行竖列的二维数据

    2. 对一个大的数组中的元素,进一步分类

  如何:

    创建:

     1. 先创建空数组,再添加子数组:

       var arr=[];

       arr[0]=[2,2,4,0];

       arr[1]=[0,2,2,0];

     2. 在创建数组同时,初始化子数组

       var arr=[

 [2,2,4,0],//0

         [0,2,2,0],//1

         ...

       ];

    

    访问元素:

      arr[r][c]:访问arrr位置的子数组中的c位置的元素

      越界: r不能越界

 

    遍历: 外层循环控制行,内层循环控制列

      for(var r=0;r<arr.length;r++){

       for(var c=0;c<arr[r].length;c++){

 arr[r][c]//当前元素    

       }

      }

 

2. ***String:

  什么是: 一串字符组成的只读字符数组

    vs数组: 1. 下标访问每个字符

           2. length属性标识字符个数

           3. for循环遍历每个字符

           4. 数组中不直接修改原数组的API,字符串也可用

            concat,slice

 

  内置对象: ES标准中规定的,浏览器已经实现的对象。包括11:

    String Number Boolean——包装类型

    Array Math Date RegExp

    Error

    Function Object

    Global(在浏览器中被替换为window)

 

  包装类型:专门封装原始类型的值,并提供对原始类型的值进行操作的API 的对象

   为什么:原始类型的值,本身什么API都没有

   何时: 只要试图用原始类型的值调用方法时

         都会自动创建包装类型对象

   如何使用: 自动创建和调用。

 

StringAPI: 所有StringAPI,都无权修改原字符串,必须返回新字符串

1. 大小写转换:

   何时使用: 不区分大小写时

  str.toUpperCase();

  str.toLowerCase();

2. 获取指定位置的字符:

  str.charAt(i) => str[i]

  str.charCodeAt(i)

    获得stri位置的字符的unicode

    互逆操作: unicode号转为原字符

   var char=String.fromCharCode(unicode);

3. 获取子字符串:

  str.slice(starti,endi+1);

  str.substring(starti,endi+1);

    用法和slice完全一样。

    不支持负数参数:

      解决: str.length-n

  str.substr(starti,n);

    截取strstarti开始后的n个字符

4.检索关键词:

  1. 检索一个固定的关键词出现的位置

    var i=str.indexOf("关键词",fromi);

     strfromi位置开始,找下一个"关键词"出现的位置。

     如果找不到了,返回-1

     简写: 省略fromi,表示从0位置开始找

 

    var i=str.lastIndexOf("关键词",fromi)

     strfromi位置开始查找前一个"关键词"出现的位置

     如果找不到,返回-1

     简写: 省略fromi, 表示从末尾开始找

     何时: 只要查找最后一个xxxx

 

 

*******************************************************************************

 

Day 08

 

回顾:

1.数组:

  排序: arr.sort();

    function cmp(a,b){return a-b};

    arr.sort(cmp);

    function cmp(a,b){return b-a};

  栈和队列:

    : FILO

     结尾: : arr.push()

           : var last=arr.pop();

     开头: : arr.unshift()

           : var first=arr.shift();

    队列:FIFO

     结尾入:arr.push()

     开头出:var first=arr.shift();

  二维数组:

    遍历:

     for(var r=0;r<arr.length;r++){

      for(var c=0;c<arr[r].length;c++){

        arr[r][c]//当前元素

      }

     }

2. String:

 大小写转换:

   str.toUpperCase();

   str.toLowerCase();

 获得指定位置的字符:

   str.charAt(i) => str[i]

   var unicode=str.charCodeAt(i)

    var char=String.fromCharCode(unicode)

 获取子字符串:

   str.substring(starti,endi+1)

       => str.slice(starti,endi+1)

   str.substr(starti,n)

 检索关键词:

   1. 仅检索一个固定关键词出现的位置

     var i=str.indexOf("关键词",fromi);

    找所有位置:

     while(

      (i=str.indexOf("关键词",i+1))!=-1{

i//就是找到关键词的位置

     }

    找最后一个:

     var i=

       str.lastIndexOf("关键词",fromi)

    

    问题:每次只能检索一个固定的关键词,无法实现按规则模糊检索

 

正课:

1. *****正则表达式:

2. ***String中的正则API

   查找

   替换

   切割

 

1. 正则表达式(Regular Expression

 什么是: 规定字符串中字符出现规律的规则

 何时使用:

    1. 只要按规则模糊匹配多个关键词时

    2. 只要按规则验证字符串是否符合要求

 查看正则的逻辑: regexper.com

 语法:

  1. 最简单的正则,就是关键词原文

  2. 字符集: 规定1位字符可用的备选字符的列表: [备选字符列表]

    何时使用: 如果一位字符,有多种选择时

    简写: 如果字符列表中部分字符连续,就可用-省略中间的字符

     比如: 1位字母:[A-Za-z]

           1位数字:[0-9]

    除了: [^xxx] 除了xxx都行

  3. 预定义字符集:

      对部分常用字符集的简化

      1位数字 \d  => [0-9]

      1位字母,数字,_ \w => [A-Za-z0-9_]

      1位空字符(空格,换行,Tab): \s

 

      . 匹配除回车换行外的所有字符

     强调: 只有需求和预定义字符集完全匹配时,才能使用预定义字符集。

  4. 量词: 专门规定一个字符集出现次数的规

则。

    有明确数量限制:

      字符集{n,m}  字符集可出现至少n次,最多m

      字符集{n,}  字符集至少出现n次,多了不限

      字符集{n}  字符集必须出现n

 

    没有明确数量显示:

      字符集?   可有可无,最多一次

      字符集*   可有可无,多了不限

      字符集+   至少一次,多个不限

    强调: 字符集,默认仅修饰相邻的前一个字符集。

 

   身份证号:

    15位数字

    再跟2位数字

    最后一位可以是数字或x,X

    \d{15}(\d{2}[0-9xX])?

 

  5. 分组和选择:

    分组: 将多个字符集用()包裹为一组

      何时: 为了让一个两次同时修饰多个字符集。

    选择: 其实就是程序中的或者 |

     规则1|规则2  只要满足其一即可

 

   手机号:

     +860086? 可有可无,最多一次

     空字符  可有可无,多了不限

     1

     3,4,5,7,8之中挑一个

     9位数字

    ^(\+86|0086)?\s*1[34578]\d{9}$

 

  6.指定匹配位置:

    ^ 字符串开始位置

    $ 字符串结尾位置

    何时: 1. 验证时,都要前加^,后加$

      2. 仅匹配开头的或结尾的关键词

    

  密码强度:

    6~8位字母,数字的组合,至少包含一位大写字母和一位数字

    预判: 从头到尾判断字符串是否符合指定规则。

     1. 如果不都由字母组成:

       说明,可能有数字或特殊符号

      (?![A-Za-z]+$)

     2. 如果不都由小写字母和数字组成:

       说明,可能有大写字母或特殊符号

      (?![a-z0-9]+$)

     3. 必须由字母和数字组成:

排除特殊字符的干扰

      [A-Za-z0-9]{6,8}

 

   ^(?![A-Za-z]+$)(?![a-z0-9]+$)[A-Za-z0-9]{6,8}$

 

2. String正则API

 检索关键词:

   1. indexOf: 不支持正则

   2. 判断是否包含符合规则的关键词:

     var i=str.search(/正则/);

      查找str中是否包含符合正则要求的关键词。

      如果找到,返回关键词的位置

      如果找不到,返回-1

    强调: search没有第二个参数fromi,不能指定下次开始查找的位置,始终只能找第一个关键词的位置。所以,只能用作判断有没有。

    

 

正课:

1. String中的正则API

2. RegExp

 

1. String中的正则API:

检索: 4:

  1. 查找一个固定关键词的位置

    var i=str.indexOf("关键词",fromi);

    var i=str.lastIndexOf("关键词",fromi)

    问题: 不支持正则

  2. 判断字符串中是否包含符合规则的关键词

    var i=str.search(/正则/);

      始终返回第一个关键词的位置

      如果没找到,返回-1

     问题: 1. 只能找第一个

           2. 只能获得位置,无法获得内容

  3. 获得每个关键词的内容:

    var kwords=str.match(/正则/ig);

      获取str中所有和正则匹配的关键词

      返回: 一个包含所有关键词的数组

          没找到,返回null

      强调: 只要一个方法可能返回null,就都要先验证不是null,再使用。

      强调: 所有正则表达式默认只匹配一个关键词。除非在第二个/后加g,表示全部。

          如果希望忽略大小写: i

     问题: 无法获得每个关键词的位置

 

    如果match不加g:

      仅返回第一个关键词的内容和位置

      kwords:[0:"关键词",index:i]

 

   4. 即获得每个关键词的内容,又获得每个关键词的位置?

 

替换: str中和正则匹配的敏感词替换为指定内容。

  str=str.replace(/正则/ig,"替换值");

  高级: 如果希望根据关键词的不同,替换不同的内容时:  

  str=str.replace(/正则/ig,

    function(kwd,$1,...){

      return 根据kwd返回不同的值;

    }

  )

  

  $1,$2,...:如果需要对关键词中部分内容单独处理时:2:

     1. 在正则中用(),将要单独操作的部分分组。在匹配时,每个分组会自动获得从1开始,连续不重复的序号

     2. replace内部的函数的参数中可用$1,$2...获得第i个分组的子内容。

 

  练习:

  :正则:

   \b: 单词边界: ^ 空格 标点 $

   何时使用: 今后,只要匹配单词,必须前后加\b

  

  扩展:

    1. 删除:将关键词替换为空字符串:

    2. 格式化: 2:

       1. 用正则将原字符串分组

       2. replace第二个参数中用$i方式拼接新的格式。

 

  :正则: 一位汉字:[\u4e00-\u9fa5]

 

切割: 将字符串,按匹配的分隔符,分割为多个子字符串

  var subs=str.split(/正则/);

 

*******************************************************************************

 

Day 09

 

回顾:

1. 正则:

  1. 最简单的正则就是关键词原文

  2. 字符集: [备选字符列表]

     简写: [A-Za-z] [0-9] [\u4e00-\u9fa5]

     除了: [^xxx]

  3. 预定义字符集:

      \d => [0-9]

      \w => [A-Za-z0-9_]

      \s => 空字符: 空格,制表符...

      . => 除回车换行外的一切字符

  4. 量词:

      1. 有明确数量限制:

         字符集{n,m} 至少n次,最多m

         字符集{n,} 至少n次,多了不限

         字符集{n}  必须n次,不能多也不能少

      2. 没有明确数量:

         字符集?  可有可无,最多一次

         字符集*  可有可无,多了不限

         字符集+  至少一次,多了不限

  5. 选择和分组:

    规则1|规则2

    (规则1规则2)

      每个分组会自动获得一个从1开始连续不重复的需要

  6. 指定匹配位置:

    ^ 字符串开头

    $ 字符串结尾

    \b 单词边界

  7. 密码强度: 预判

    6~8位字母和数字的组合,至少包含一位大写字母和一位数字

    (?![A-Za-z]+$)(?![a-z0-9]+$)[A-Za-z0-9]{6,8}

 

2. String中的正则API:

检索:

  1. 查找一个固定关键词出现的位置

   var i=str.indexOf("关键词",fromi)

   var i=str.lastIndexOf("关键词",fromi)

  2. 判断是否包含符合规则的关键词:

   var i=str.search(/正则/i)

  3. 获得所有关键词的内容:

   var kws=str.match(/正则/ig);

   如果不加g:

     match也相当于search,但可获得关键词内容: [0:"关键词",index:i]

  4. 即获得每个关键词的内容,又获得每个关键词的位置: reg.exec(str)

   

替换:

 简单:将所有关键词替换为统一的替换值

   str=str.replace(/正则/ig,"替换值");

 高级:根据关键词的不同,替换不同的值

   str=str.replace(/正则/ig,

      function(kw,$1,$2,...){

        return 根据kw判断返回不用替换值         }

   );

 扩展:

   1. 删除: 将关键词替换为""

   2. 格式化: 2:

     1. 用正则将原字符串分组

     2. replace的第二个参数中用$i拼接出新的内容。

 

切割:

  var subStrs=str.split(/正则/);

    固定套路: var chars=str.split("")

 

正课:

1. RegExp

2. Math

3. Date

 

1. RegExp: 封装一条正则表达式,并提供用正则执行验证和查找的方法的对象

 何时使用:

  检索: 即检索每个关键词内容,又检索位置

  验证: 检查字符串是否符合正则表达式的要求

 

 如何使用:

  创建: 2:

   1. 只用正则直接量: var reg=/正则/ig;

     何时使用: 如果正则表达式是固定的,不需要动态生成。

     特殊符号: 直接量中的/都要转为\/

       /<\/li><li>/

   2. new:

    var reg=new RegExp("正则","ig");

     何时使用: 如果正则表达式不是固定的,需要动态生成

     特殊符号:

       \ " '都要转义为:\\ \"  \'

     "\\d{6}" "href=[\'\"]..."

 

RegExp API:

检索: 即检索每个关键词的内容,又检索每个关键词的位置

  var arr=reg.exec(str)

    找出str中当前位置后和reg匹配的下一个关键词。

  原理:

    reg.lastIndex: 标识下次开始查找的位置

        默认0

    exec: 每执行一次,3件事:

     1. reg.lastIndex位置开始找下一个关键词

     2. 返回:

       [0:"关键词",1:"$1",2:"$2",...]

       .index-> 返回本次找到的关键词位置

       强调: 如果找不到,返回null

     3. 自动修改reg.lastIndexindex+关键词的字符个数(跳过当前关键词)

 

  练习:

   正则:

   贪婪模式: 默认正则表达式都会匹配尽量长的符合规则的字符串。

   懒惰模式: 仅匹配最短的符合规则的字符串

     贪婪改懒惰?  .*?  .+?

 

验证: 检查一个字符串是否符合正则表达式的要求。

  var bool=reg.test(str);

     检查str是否符合reg的要求

     如果符合,返回true,否则返回false

  问题:默认test方法只要部分匹配就返回true

  解决:验证都要前加^,后加$,要求从头到尾必须完整匹配。

 

2. Math: 专门封装数学计算使用的常量,并提供执行数学计算的API的对象

    强调: 不能new!直接使用Math.xxx

Math API:

取整:

  1. 上取整: 只要超过,就取下一个整数

    Math.ceil(n);

  2. 下取整: 只要超过,就去掉小数部分]

    Math.floor(n);

  3. 四舍五入取整: Math.round(n)

   vs n.toFixed(d)

   Math.round只能取整,返回的是number

   n.toFixed(d),可指定小数位数,但返回的是string

   自定义round:

   

乘方和开平方:

  Math.pow(底数,) : 计算乘方

   比如: 102次方: Math.pow(10,2);

  Math.sqrt(n):n的平方根

   

 

*******************************************************************************

 

Day 10

 

回顾:

1. RegExp:

  检索: var arr=reg.exec(str);

    while((arr=reg.exec(str))!=null){

      arr[0]//本次找到的关键词

      arr[i],RegExp.$i //i个分组的子内容

      arr.index//本次找到的关键词位置

    }

  验证: var bool=reg.test(str);

    前加^,后加$

2. Math:

取整:

  上取整: Math.ceil(n);

  下取整: Math.floor(n);

  四舍五入取整: Math.round(n);

   vs n.toFixed(d)

   function round(num,d){

    return Math.round(num*Math.pow(10,d))

   /Math.pow(10,d)

   }

 

乘方和开平方:

 Math.pow(底数,);

 Math.sqrt(n)

 

 

正课:

1. Math:

  maxmin

  random

2. Date:

 

1. Math: 不能new

最大值和最小值:

  Math.max(1,2,...)

   获得给定值中的最大值

  Math.min(1,2,...)

   获得给定值中的最小值

  问题: maxmin不支持数组参数

    解决: Math.max.apply(null,arr)

      获得arr中的最大元素

 

随机数:

  Math.random() -> 返回0<=r<1之间的一个随机小数。  

  0~max之间取随机整数:

  Math.floor(Math.random()*(max+1));

  min~max之间取随机整数:

Math.floor(Math.random()*(max-min+1)+min)

 

2. Date: 封装一个时间点,并提供操作时间的API的对象

  何时使用: 只要存储日期或时间,或者要对时间进行计算时。

  如何使用:

    创建: 3:

     1. 创建一个日期对象,同时自动获得客户端当前系统时间:

       var now=new Date();

     2. 创建一个日期对象,并封装自定义时间:

      var date=

       new Date("yyyy/MM/dd hh:mm:ss");

      var date=

       new Date(yyyy,MM-1,dd,hh,mm,ss)

     3. 复制一个日期对象:

       为什么:为了保留计算之前的原时间

       何时: 只要要求同时保留计算前后的两个时间时,都要先复制原时间,再用副本计算新时间。   

       如何: var date1=new Date("xxx")

             var date2=new Date(date1);

  日期对象的原理:

    日期对象中封装的是一个从1970110点至今的毫秒数

 

Date API:

 分量: FullYear Month Date Day

       Hours Minures Seconds Milliseconds

 1. 每个分量都有一对儿getXXX/setXXX方法

    getXXX方法负责获取分量的数值

    setXXX方法负责将新值更新到分量

      强调: set可自动调整时间进制

    特殊:Day 星期,没有set

 2. 年月日星期,都是单数,不带s

    时分秒毫秒,都是复数,带s

 3. 返回值:(取值范围)

    除了月中的日(Date),是从1开始到31结束

    其余都是从0开始,到进制-1结束

    比如:

     Month: 0~11 在赋值或取值时都要修正

     Date: 1~31

     Hours: 0~23

     Minutes/Seconds: 0~59

     Day: 0~6 ,,,...,六  不用修正

 

  计算:

   1. 两日期对象可相减,结果毫秒差

   2. 对任意分量做加减:3:

     1. 取分量: date.getXXX();

     2. 做加减:

     3. set回去: date.setXXX(n)

    简写: date.setXXX(date.getXXX()+n)

 

  date 2 string:

   date.toString()/toGMTString();

   date.toLocaleString(); 转为当地时间格式,即包含日期,又包含时间

   date.toLocaleDateString(); 转为当地时间格式,仅包含日期

   date.toLocaleTimeString(); 转为当地时间格式,仅包含时间

 

正课:

1. 错误处理

2. *****Function

 

1. 错误处理:

  错误: 程序在执行过程中遇到的异常中断

      当发生错误时,程序会报错,退出。

  错误处理: 即使发生错误,也保证程序不中断退出的机制。

  如何:

    try{

      可能发生错误的正常逻辑

    }catch(err){

      只有发生错误时才执行的错误处理代码:

      //包括: 1. 记录日志:

            //2. 提示用户

            //3. 保存数据

    }finally{

      //无论是否出错,都一定会执行的代码

      //包括: 释放内存

    }

  其中err:

   一旦try中的程序发生错误,js会自动创建一个Error类型的对象。

   Error:专门封装错误信息的对象。

     6:

     SyntaxError: 语法错误

     ReferenceError: 引用错误,要使用的变量,或对象,没找到。

     TypeError: 类型错误,指错误的使用了类型的方法。

     RangeError: 参数超范围

 

     URIError,EvalError

 

  如果可以提前预知错误的原因,就可用if...else...代替try catch

   

  判断浏览器兼容性:

  try{

   new XMLHttpRequest

();

   提示: 支持Ajax

  }catch(){

   提示: 不支持Ajax

  }

  也可用if...else代替

  

  鄙视题: try catch中的return

    如果finally中有return,则使用finally中的return返回

    如果finally中没有returntry中的return,会先获得要返回的值,但挂起,暂不返回。要等待finally中代码执行完,才返回。

 

  主动抛出错误:

   何时: API的开发者,向API的调用者提示错误时。

   如何抛出: throw new Error("信息")

 

2.*****Function

  js中的一切函数都是一个对象

  创建函数: 3:

   1. 声明方式:

     function 函数名(参数列表){

       函数体;

       return 返回值;

     }——被声明提前(hoist)

     其中:function是创建一个新函数的意思

         函数其实是一个对象

   函数对象中封装的不是数据,而是代码段。

         函数名仅是引用函数对象的普通变量

   2. 函数直接量:

     var 函数名=function(参数列表){

     不会被声明提前。

     何时: 如果不希望函数定义被提前时,就必须用直接量。

   3. new:

   var 函数名=

     new Function("参数名1",...,"函数体")

    何时: 如果函数的参数名和函数体可能在运行时动态生成。

 

***重载(overload): 相同函数名,不同参数列表的多个函数,在调用时,可根据传入的参数不同,自动选择对应的函数执行。

  为什么: 为了减少函数的个数,减轻使用者的负担。

  如何: js中默认不支持重载的语法

   变通: arguments对象

    函数中自动创建的,接收所有传入函数的参数值得类数组对象。

      类数组对象: 长的像数组的对象

        vs 数组: 相同: 1. 用下标访问元素

                       2. length属性

           不同: 不是数组类型,无法使用数组类型的API

 

*******************************************************************************

 

Day 11

 

回顾:

1. Math:

  Math.random()

  0~max:

   Math.floor(Math.random()*(max+1))

  min~max:

   Math.floor(Math.random()*(max-min+1)+min)

2. Date:

  创建:3:

   1. 创建日期对象并自动获得当前客户端系统时间:

    var now=new Date();

   2. 创建日期对象保存自定义时间:

    var date=

      new Date("yyyy/MM/dd hh:mm:ss");

    var date=

      new Date(yyyy,MM-1,dd,hh,mm,ss);

   3. 复制一个日期对象:

    var date2=new Date(date1);

 

Date API:

  FullYear Month Date Day

  Hours Minutes Seconds Milliseconds

 1.每个分量都有一对儿get/set方法

   Day没有set

 2.年月日星期 单数,不带s

   时分秒毫秒 复数,s

 3.月中的日(Date): 1~31

   其余都是: 0~进制-1

   只有Month需要修正: 计算机中的月比现实中少1

 

 计算:

  1. 两日期对象可相减,结果是毫秒差

  2. 对任意分量做加减:

   date.setXXX(date.getXXX()+n)

 

 to String:

  date.toString();

  date.toGMTString();

  date.toLocaleString();

  date.toLocaleDateString();

  date.toLocaleTimeString();

 

3.错误处理:

  try{

    可能出错的正常代码

  }catch(err){

    只有出错才执行的错误处理代码

  }finally{

    无论是否出错总会执行的代码

  }

 

  Error:

   SyntaxError,ReferenceError,TypeError

   RangeError, URIError, EvalError

 

  主动抛出异常:

  throw new Error("错误信息");

 

4.Function:

 创建:

  1. 声明:

   function 函数名(参数列表){

     函数体

     return 返回值;

   }——被声明提前(hoist)

  2. 直接量:

   var 函数名=function(参数列表){

    ——不会被声明提前

  3. new:

   var 函数名=

    new Function("参数名",...,"函数体")

 

  js中,函数其实就是一个对象。

    封装了一段可反复执行的代码段。

    函数名其实只是一个引用函数对象的变量

 

 重载:(overload)

   何时: 如果一件事,根据不同的参数,执行不同的逻辑时

   如何:

     arguments: 函数中自动创建的

           自动接收所有传入函数的参数值得

           类数组对象

     arguments[i] //获得第i个参数值

     arguments.length //获得参数个数

 

正课:

1.*****Function

  匿名函数

****作用域和作用域链

*****闭包

 

1.匿名函数:

  什么是: 在创建时,不被任何变量引用的函数。

  为什么: 节约内存

  何时: 只要一个函数只用一次,就释放

  如何使用:

   1.回调: 创建一个函数后,将函数对象传递给其他函数调用。

     比如:

      arr.sort(

function(a,b){return a-b}

      );

      arr.replace(reg,function(){

return xxx;

      })

   2.自调: 创建一个函数,然后立刻调用执行

          执行后,立刻释放

     (function(参数列表){

        函数体;

        return 返回值;

     })(参数值);

     何时: 如果一项任务仅执行一次,且使用了仅属于当前任务的变量时,就要将变量和任务代码封装在一个匿名函数中,自调

 

****作用域和作用域链:

 作用域(scope): 一个变量的可用范围

            本质: 存储变量的对象

 函数的原理:

  程序开始执行:

    创建ECS(Execution Context Stack):

      顺序保存正在调用的函数的执行环境

    ECS中压入第一个EC:

      EC:函数调用时,引用所有变量的元素。

    创建全局作用域对象window:

      EC引用window

  函数定义时: 创建函数对象

         在全局创建函数名变量引用函数对象

         在函数对象中添加一个scope属性:

           引用函数来自的作用域对象

  函数调用时:

    ECS中压入要调用函数的执行环境EC

    创建函数作用域对象(活动对象AO):

      AO:保存本次函数调用时,使用的所有局部变量的对象。

      AO中添加parent属性,引用函数对象的scope属性指向的作用域。

    EC中的scope chain属性引用AO对象

 

  函数调用后: 本次调用的函数的EC出栈

      导致:AO释放

            导致: 局部变量一同释放

 

 作用域链(scope chain):

 由各级作用域对象,逐级引用形成的链式结构

   控制变量的使用顺序:

    优先使用AO中的局部变量

    如果局部没有,才延作用域链向下找,到window

    如果window也没有才报错

 

*****闭包(closure):

  重用局部变量,并保护变量不受污染的机制

  为什么:

    全局变量: 随处可用,可反复使用

           : 极易被污染

    局部变量: 不会被污染

           :仅函数内可用,且不可重用

  何时: 只要希望重用一个局部变量,又不希望局部变量被污染时

  如何: 3:

    Step1: 将受保护的变量和操作变量的函数封装在一个外层函数中定义。

    Step2: 外层函数,要将内层函数队形返回

    Step3: 使用者调用外层函数,获得内层函数对象。

 

正课:

1. *****Function

  闭包

2. *****OOP

 

1. *****Function:

闭包:

 如何: 3:

  1. 用外层函数封装受保护的变量和操作变量的内层函数

  2. 外层函数返回内层函数的对象

  3. 使用者调用外层函数,获得内层函数的对象。

 

 三大特点:

  1. 外层函数

  2. 受保护的变量

  3. 内层函数

 

 BS:

  1. 先找受保护的变量:

    1. 外层函数的局部变量

    2. 内层函数中被使用

    判断当外层函数结束时,受保护的变量最终的值。

  2. 找外层函数返回的内层函数对象:

    1. return function

    2. 直接给全局变量赋值一个function

    3. 将多个内层函数放入数组或对象中,批量返回。

  结论:

  同一次外层函数调用返回的多个内层函数对象共用同一个受保护的变量。

  先后两次外层函数调用返回的两个内层函数对象,分别使用各自的受保护的变量副本,互不影响。

 

  : 重用变量,且保护其不被篡改

  : 占用更多的内存空间。

      无法自动释放

 

2.*****面向对象:

  什么是: 程序中都是用对象来描述现实中一个具体事物。

    什么是对象: 程序中封装现实中一个具体事物的属性和功能的程序结果

       事物的属性,会成为对象的属性

       事物的功能,会成为对象的方法

  为什么: 更符合人的想法。

  如何使用: 2:

    1. 先用对象描述一个事物的属性和功能

       -创建对象/封装

        封装: 将事物的属性和功能集中定义在一个对象中。

      3:

      1.对象直接量:

        var obj={

          属性名:,

          方法名:function(){

            //对象的方法中,要使用对象自己的属性,必须写成"this.属性名"

             //当前对象的...

          }

        }

       this: 指正在调用方法的.前的对象

***js中一切对象底层都是hash数组

 

      2.new:

       var obj=new Object();

       obj.属性名=;

       obj.方法名=function(){

 ...this.属性名...

       }

       其中new可省,()也可省,但不能同时省略。

      3.反复创建多个相同结构的对象:

        2:

        1.定义构造函数:

         什么是: 专门描述一类对象统一结构的函数。

         何时: 只要反复创建多个相同结构的对象时。

         为什么: 代码重用——优

         如何:

           function 类型名(属性参数){

             this.属性名=属性参数;

             this.方法名=function(){

               ...

             }

           }

       2.new调用构造函数:

         var obj=new 类型名(属性值);

      new: 4件事儿:

       1. 创建了一个空对象:

       2. ?

       3. 用空对象调用构造函数

       4. 返回新对象地址给变量

 

       : 没有解决内存浪费的问题

 

    2. 再按照逻辑的需要,依次调用对象中的功能来操作对象的属性。

      访问对象的成员(属性和方法):

        操作对象的属性: obj.属性名

          其实就是一个放在对象中的普通变量而已。

        特殊:

         访问对象中没有的属性,不报错,返回undefined.

         为对象中不存在的属性赋值,不报错,会自动添加属性,保存属性值。

        调用对象的方法: obj.方法名();

          其实就是一个放在对象中的普通函数而已。

 

  *******************************************************************************

 

Day 12

 

回顾:

1.OOP:

 创建:

   1. 直接量:

     var obj={

      属性名:,

      方法名:function(){

        this.属性名

      }

     }

   2. new:

     var obj=new Object();

     obj.属性名=;

     obj.方法名=funciton(){

       this.属性名;

     }

   3. 用构造函数,反复创建多个相同结构的对象

     2:

     1. 定义构造函数:

       function 类型名(属性参数列表){

         this.属性名=属性参数;

         this.方法名=function(){

           this.属性名...

         }

       }

   

       : 代码重用

       : 没有解决内存浪费的问题

 

     2. new调用构造函数:

       ——实例化(instance)一个xxx类型的对象。

      var obj=new 类型名(属性值列表)

       其中:obj也成为xx类型的一个实例

 访问对象成员:

   obj.属性名 => obj["属性名"]

   obj.方法名();

 

 本质: js中一切对象底层都是hash数组,属性名是字符串类型的key,属性值是value

 

正课:

1.*****OOP:

面向对象的理解:

  面向对象三大特点:

   封装:将一个/一类事物的属性和功能集中定义在一个对象中

     为了代码重用!

   继承:父对象中的成员,子对象无需重复创建,即可直接使用。

     为了即代码重用,又节约内存

   多态:同一个方法,在不同情况下,表现出不同的状态。

     为了体现子对象与父对象之间的差异。

 

继承: js中的继承都是通过原型对象实现的

    也成为: 原型继承/继承原型

 原型对象(prototype): 集中存储一类对象共有成员的父对象。

   何时: 只要多个子对象中,拥有相同的成员,就都要集中定义在父对象(原型对象)中一份,然后所有子对象共用!

   如何:

    创建: 在创建构造函数时,会自动创建该类型的原型对象prototype

    何时继承:

     new: 2. 设置新对象的__proto__属性继承构造函数的原型对象

    如何向原型对象中添加共有成员:

     类型名.prototype.共有成员名=

 

  原型链: 由各级父对象逐级继承,实现的链式结构。

    任何对象都有__proto__继承其父对象

    Object.prototype是所有对象的顶级父对象。Object.prototype.__proto__null

    Function.prototype是所有函数对象的父对象。Function.prototype.__proto__Object.prototype

    原型链控制着成员的使用顺序:

     优先使用当前对象本地的自有成员

     如果自己没有,才延原型链向父级找

     如果到Object.prototype没找到,返回undefined

    vs 作用域链: 控制着变量的使用顺序

  不带.直接访问的变量,走作用域链

  .访问的对象成员,都走原型链

 

  正确的访问对象的成员:

   原则:

    修改原型链上的共有成员:必须用父对象改

    修改自有成员: 必须用当前子对象本身

    错误: 禁止使用子对象修改共有成员

  如何判断成员是自有还是共有:

    自有: 直接定义在当前对象本地的成员

    共有: 对象本地没有,从原型链上继承来的成员。

    判断自有:

    var bool=obj.hasOwnProperty("成员名")

      判断"成员名"是否直接定义在obj本地

      如果是自有,就返回true

      否则返回false

    判断共有:

      不是自有,且原型链上有

      !obj.hasOwnProperty("成员名")

       &&(obj.成员!==undefined)

           "成员名" in obj

       in: 判断"成员名"是否包含在obj的原型链上。(可检查整个原型链)

 

  删除: delete obj.属性名

    不能用子对象删除共有属性

 

正课:

1.*****OOP

 扩展内置对象的API

 原型API

 自定义继承

 

1.扩展内置对象的API:

 为什么: 解决浏览器兼容性问题

 何时: 如果想在旧的浏览器上,使用新浏览器的API,就需要再旧浏览器扩展内置对象的API

 如何: 都是将自定义的API添加到指定类型的原型对象上。

 

2.原型API:

  获得原型对象:2:

   通过构造函数获得: 构造函数.prototype

   通过子对象获得: obj.__proto__ 兼容性

     Object.getPrototypeOf(obj)

       获得obj对象的父对象(原型对象)

  判断指定对象是否是子对象的父对象:

    father.isPrototypeOf(child)

    判断father对象,是否是child对象的父对象。

     如果fatherchild的父对象,就返回true,否则返回false

     强调: 检查整个原型链

  判断指定对象是否是指定构造函数的实例:

    child instanceof 构造函数(mather)

    判断child是不是被构造函数实例化出的

     强调: 也检查整个原型链

 

  鄙视题: 判断一个对象是不是数组类型

          有几种办法?

   typeof: 只能识别原始类型和函数

          无法进一步区分不同的引用类型

   1.isPrototypeOf

   2.instanceof

   3.class属性: 记录了对象创建时的类型名

            一旦对象创建,不可更改

      只有Object.prototype中的toString方法才能输出class属性

     问题: 内置对象的原型对象中都重写了新的toString方法,阻碍了子对象直接调用原始的toString方法

     解决: call强行调用!

要调用方法的完整签名.call(调用方法的对象)

   4.Array.isArray(obj)

     专门用于检测obj是不是数组类型

     原理同第三种方法

 

总结:

  call: 用一个对象强行调用一个本来无法调用到的函数。

    何时: 希望打破原型链的限制,直接调用一个本不可调用的函数

    如何:

     要调的函数.call(对象)

  

  添加一个新方法,如何选择加在构造函数上,或者加在原型对象中?

    如果希望指定类型的所有子对象都可访问时,就放在原型对象中

    ——必须通过实例化的对象调用

        也成为实例方法

    如果无法确定将来调用函数时的对象的类型,就不能放在原型对象中。要放在构造函数上。——static静态方法

 

多态:

 重写(override): 如果子对象觉得父对象继承来的成员不好用,就可在本地定义和父对象成员同名的自有成员——优先使用自有成员,而屏蔽了父对象的共有成员。

 

3. 自定义继承:

  3:

  1. 修改一个对象继承另一个父对象:

    child.__proto__=father;

     => Object.setPrototypeOf(

           child,father

        )  

    设置child继承father

  2. 批量修改所有子对象的父对象:

    时机: 在开始创建子对象之前,就修改原型对象。

    构造函数.prototype=father

    

  3. 两种类型间的继承:

    问题: 两种类型间,有部分相同的属性结构,和共同的方法。

    解决: 抽象出一个公共的父类型

      将子类型中相同的部分属性和方法,定义到父类型中。

    如何实现两种类型间的继承:

     1. 设置子类型的原型对象继承父类型的原型对象。

      Object.setPrototypeOf(

        子类型的原型对象,

        父类型的原型对象

      );

     2. 借用父类型的构造函数:

      父类型构造函数.call(this,参数,...)

     

 

*******************************************************************************

 

Day 13

 

回顾:

1. OOP:

 面向对象三大特点:

   封装:将现实中一个事物的属性和功能集中定义在一个对象中。

    3:

     1. 直接量:(创建一个单独的对象)

      var obj={

        属性名:,

        方法名:function(){

          ...this.属性名...

        }

      }

     2. new:

      var obj=new Object();

      obj.属性名=;

      obj.方法名=function(){

        ...this.属性名...

      }

     3. 反复创建多个相同结构的对象: 2

      1. 定义构造函数:

      function 类型名(属性参数列表){

        this.属性名=属性参数;

        /*浪费内存,已被否定

        this.方法名=function(){

          ...this.属性名...

        }*/

      }

      2. new调用构造函数: 实例化一个对象。

      var obj=new 类型名(属性值列表);

      new: 1.创建新的空对象

           2.设置新对象的__proto__继承构造函数的原型对象

           3.用新对象调用构造函数,为新对象添加规定的属性和方法。

           4.将新对象的地址保存到变量中

 

   js中一切对象底层都是hash数组

       

   继承:父对象中的成员,子对象无需重复定义,即可直接使用。

    js中的继承都是原型继承

    原型对象:集中存储一类子对象共有成员的父级对象。

    原型链: 由各级对象的__proto__属性逐级继承,形成的链式结构

      控制着对象中属性的使用顺序

 

   API:

   1. 判断指定"属性名"是否是obj的自有属性

    var bool=obj.hasOwnProperty("属性名")

   2. 判断是否是共有属性:

    !obj.hasOwnProperty("属性名")

     &&("属性名" in obj)

   3. 获取原型对象: 2:

    构造函数.prototype

    Object.getPrototypeOf(child)

   4. 删除属性: delete 对象.属性名

   5. 判断一个对象是不是数组类型:

     1. father.isPrototypeOf(child)

       判断father是否是child的原型链上的父级对象。

     2. child instanceof 构造函数

       判断child是否是构造函数的实例

     3. 输出对象的内部属性class:

Object.prototype.toString.call(obj)

        输出objclass属性

     4. Array.isArray(obj)

       判断obj是否是数组类型

   

   自定义继承: 3:

   1. 直接修改一个对象继承另一个对象:

    Object.setPrototypeOf(child,father);

   2. 修改构造函数的原型对象,批量修改之后所有子对象的父对象

    构造函数.prototype=father

    时机: 在开始创建子对象之前就修改。

   3. 两种类型间的继承: inherits&&extends

     抽象: 如果多个子类型之间有相同的属性结构和方法定义,就要抽象出一个父类型,将相同的属性结构和方法定义统计定义在父类型中。

     在子类型构造函数中借用父类型构造函数:extends

     function 子类型构造函数(...){

        //new 子类型构造()->this->新对象

  父类型构造函数.call(this,参数1,参数2,...)

        ...扩展新属性

     }

     其实: 父类型构造函数.call(this,参数1,参数2,...)可简写为:

     父类型构造函数.apply(this,arguments)

     让子类型原型继承父类型原型:inherits

     Object.setPrototypeOf(

子类型原型, 父类型原型

     )

 

   call vs apply:

    相同: 都是强行借用任意函数,并替换函数中的this为指定对象。

    不同: 参数:

      call,只能将传入借用的函数的参数,单独传入。

      apply,可将传入借用的函数的参数,以数组方式传入。apply可自动打散数组为单个参数。

 

   多态:

     重写(override):如果子对象觉得父对象继承来的成员不好用,可子定义同名的自有成员,来覆盖父对象的成员。

 

正课:

1. *****ES5:

*****对象的属性

  Object.create

  数组API

*****函数的bind()

  严格模式

 

1.*****对象的属性:

  ES认为对象就是属性的集合

  属性分为:

   命名属性:自定义的或可直接用.访问到的属性

     数据属性: 直接存储属性值得属性

       将每个属性都定义为四大特性:

         value: 实际存储当前属性值

         writable: 标识属性是否可修改

         enumerable: 标识属性是否可被for in遍历到。即使改为false,依然可用.访问到

         configurable: 标识能否删除属性或修改属性的其他特性

       为什么: 特性是对属性的保护

           configurable保护其他特性

       如何访问特性:

        Object.getOwnPropertyDescriptor(

          obj,"属性名"

        )

返回一个对象,对象中包含了属性的四大特性

       如何修改属性的特性:

     1. 只修改一个属性的四大特性:

     Object.defineProperty(obj,"属性名",{

writable:false,

        configurable:false

     })

     强调: 为了防止其他人再将writable改回true,可将configurable一并设置false

      configurable一旦改为false,不可逆。

     2. 同时修改多个属性的四大特性:

     Object.defineProperties(obj,{

属性名:{

          特性名:,

          ...

        },

        属性名:{

  特性名:,

          ...

        }

     })

        

     关于特性的默认值:

     defineProperty/defineProperties,如果要修改的属性不存在,会自动添加新属性。

     但是,被defineXXX添加的新属性,所有特性默认值为false

 

*****访问器属性: 不直接存储属性值,而是对其他属性提供保护的一种特殊属性。

       何时: 如果使用自定义的验证规则保护属性时。

       四大特性:

         set:function(val){

   验证val

   如果验证通过,才将val赋值给受保护的数据属性

         }//只要对访问器属性赋值时,自动调用访问器属性的set方法

 get:function(){

           return 受保护的数据属性的值

         }//只要使用访问器属性取值时,自动调用访问器属性的get方法

 enumerable: 同数据属性

         configurable: 同数据属性

     如何定义:

     都用defineProperty/defineProperties

 

   内部属性:不建议或不允许访问的属性

 

正课:

1. ES5:

 对象的属性

 Object.create

 数组API

*****函数的bind()

 严格模式

 

1.对象的属性:

 命名属性:

  数据属性:

  访问器属性:

   核心问题: 实际属性值存在哪儿?

     解决: 使用闭包,封装一个受保护的局部变量。

 

 内部属性:

  比如: __proto__   class

    extensible: 标识一个对象是否可扩展新属性。默认值true

    

 防篡改: 限制对已经创建的对象中的属性进行重新配置。

  为什么: 严格的语言中,要求对象一旦创建,属性不允许擅自增减。

  何时: 今后,只要不允许对已经创建的对象的属性进行添加和删除操作时。

  如何: 3个级别:

   1. 防扩展: 禁止向对象中添加新属性

     判断一个对象是否可扩展:

     Object.isExtensible(obj)

     设置一个对象不可扩展:

     Object.preventExtensions(obj)

       相当于修改objextensiblefalse

   2. 密封: 在兼具防扩展的基础上,进一步禁止删除对象中的属性

     判断当前对象是否密封:

     Object.isSealed(obj);

     修改当前对象为密封

     Object.seal(obj);

       相当于:修改objextensiblefalse

              将所有属性的configurable特性都改为false

   3. 冻结: 在兼具密封的基础上,进一步禁止修改所有属性的值

    何时: 只要希望一个对象中的属性值一旦创建,不可改变时,就要冻结对象——

     判断一个对象是否被冻结:

      Object.isFrozen(obj)

     冻结一个对象:

      Object.freeze(obj)

  

2. Object.create()

  设置继承有几种方法:

    1.Object.setPrototypeOf(child,father)

    2.构造函数.prototype

    3.两种类型间的继承:

      抽象父类型

      借用构造函数

      设置子类型原型继承父类型元素

    4.创建一个新对象,继承父对象,并扩展自有属性。

     如何:

      var child=Object.create(father,{

        新属性:{

          四大特性

        },

        新属性:{

          四大特性

        }

      })

 

3.数组API:

  1. 判断数组中每个元素是否符合要求:

    arr.every():判断数组中每个元素是否都符合指定规则的要求。

    arr.some():判断数组中是否包含符合指定规则的元素。

    如何使用:

     arr.every(function(val,idx,arr){

  return 判断条件

     })

    

  2. 遍历API:

  3. 过滤和汇总:

 

*******************************************************************************

 

Day 14

 

正课:

1.*****ES5

  数组API:

*****bind函数

  严格模式:

 

1.数组API:

  1. 判断数组中的元素是否符合要求

    arr.every(): 每个元素是否都符合要求

    arr.some(): 是否包含符合要求的元素

    如何使用:

    arr.every(function(val,idx,arr){

      return 判断条件

    });

  2.遍历API:对数组中每个元素执行相同的操作

   arr.forEach(): 对原数组中每个元素,直接做相同的操作——直接修改原数组

   arr.map(): 依次取出原数组中每个元素,执行相同操作后,放入一个新数组。

      ——返回新数组

   如何使用:

   arr.forEach(function(val,idx,arr){

      直接修改arridx位置的当前元素

   });

   arr.map(function(val,idx,arr){

      return 一个新值

   });

   其实: map也可实现forEach的功能,用法和forEach一样。

 

  3.过滤和汇总:

    arr.filter(): 筛选出原数组中符合条件的元素,组成新数组。

    arr.filter(function(val,idx,arr){

       return 判断条件

    });

 

    汇总: 将数组中每个元素统计起来,得出一个结果。

     var r=arr.reduce(

        function(prev,val,idx,arr){

   return prev+val;

        },

        startVal

     )

     其中: prev自动接收截止到目前已经统计的临时汇总结果。

           startVal是开始汇总前的初始值

 

2. bind函数:基于一个现有函数,创建一个新函数,并永久绑定this为指定对象,同时,还可提前绑定部分参数。

   何时使用: 在使用回调函数时,只要希望固定回调函数中的this时。(回调函数如果不用bind绑定的话里面的this指的是window

   鄙视题: call apply bind

     callapply: 临时借用构造函数,并临时替换函数中的this为指定对象。

       立刻执行函数

       调用后,this回复原样

      call: 参数单独传入

      apply: 参数以数组传入

     bind: 创建一个函数,并永久绑定this

       不会立刻执行新函数

       一旦被bind创建的函数,其中的this,无法再被call/apply替换

 

3. 严格模式:

  如何使用:

    在当前范围的开头: "use strice";

    写在2个地方:

      1. 写在一个函数内部的开头:

        仅函数内使用严格模式,函数外依然使用普通模式

      2. 写在一个script元素或js文件的开头

        整个js文件或script代码段都采用严格模式

 

    1. 旧项目升级,先逐个函数启用严格模式

    2. 新项目,开始就使用严格模式

 

  规定:

   1. 将静默失败升级为了错误!

   2. 不允许对未声明的变量赋值!

   3. 尽量少的或不使用arguments及其API

   4. 新增了eval作用域:

      eval中声明的变量,eval结束后,不能使用。

 

 

 

 

 

 

 

 

 

 

 

 

   

 

 

 

 

 

 

 

 

   

 

 

 

 

 

 

 

  

 

posted @ 2016-12-22 10:46  寒霜27  阅读(273)  评论(0编辑  收藏  举报