十四、ECMAScript6(ES6)
let和const
let 和 const 是ES2015 新增的两个关键字
它们的作用是创建变量 它们创建的变量是块级作用域
var 关键字 声明变量 var 创建的变量有 全局作用域 和 函数作用域 在预编译阶段 var 创建的变量会被提前到当前作用域顶部 并将变量赋值为undefined 使用 var 创建的全局变量 会 自动和window进行绑定 成为window的子属性
现在开始 放弃使用var 放弃使用var是应为它有一些不合理的地方
取代var的就是 let 和 const
- let 和 const 声明的变量 不与window绑定
- let 和 const 声明的变量 不会在预编译阶段 提前赋值(先声明后使用)
- let 和 const 声明的变量 是块级作用域 变量仅在当前代码块中有效(代码块 指的是大括号)
- let 和 const 不允许重复的变量声明
let
console.log(num); //报错
let num = 10;
console.log(num);// 10
console.log(window.num);// undefined
let a = 3;
if (true) {
// let a = 10; //10
console.log(a);//3
if (true) {
// let a = 5; //5
console.log(a);//3
}
}
console.log(a);//3
let a = 3;
let a = 5;
console.log(a);//出错 因为不能重复的声明
for语句有一个特殊的地方 设置循环的变量是这部分的一个父级作用域,循环体中是一个独立的子级作用域 for语句在使用let声明时 是两个作用域
for (let i = 0; i < 5; i++) {
let i = 3;
console.log(i);//3
}
console.log(i);// 出错i not is defined
let arr = [];
for (let i = 0; i < 3; i++) {
arr[i] = function () {
console.log(i);
}
}
arr[1](); //1
暂时性死区 只要在块级作用域中存在let命令 它所声明的变量就会 绑定 这个区域,不受外界影响
let num = 3;
if (true) {
console.log(num);
let num = 5;
console.log(num);
}
const
const 命令 cosnt 用于变量声明 声明的变量值是不允许改变的 const 声明的是常量 常量的值是不可变的 const 必须在声明时就进行赋值 且只能进行1次赋值
const num = 10;
num = 3;
console.log(num);
const a;
console.log(a);
对象是引用类型 引用类型的数据存在堆中 栈中报错的是引用地址 const 判断值是否改变 判断的是栈中数据 如果栈中保存的是地址 在不修改地址的前提下 可以修改对象的属性
保存引用类型数据时 优先使用const
变量声明的原则 const的优先级高于let
const o = {
x: 1,
y: 2
};
o.x = 5;
o.y = 6;
console.log(o);
const arr = [1, 2, 3, 4, 5];
arr.push(6);
console.log(arr);
解构
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。
let a = 1;
let b = 2;
let c = 3;
- 变量声明
- 赋值
- 从...中提取值(解构)
let [a, b, c] = [1, 2, 3];
console.log(a);//1
console.log(b);//2
console.log(c);//3
const arr = [1, 3, 6];
let [num1, num2, num3] = arr; // 解构赋值 将数组解开 赋值给变量
console.log(num1);//1
console.log(num2);//3
console.log(num3);//6
所谓解构赋值 是将数组 的值 依次 赋值给前方的变量 并且左右采用的是相同的结构进行匹配 如果结构不同会导致结构失败
let [a, b, c] = [1, 2];
console.log(a);//1
console.log(b);//2
console.log(c);//undefined
let [a, , c] = [1, 2, 3];
console.log(a);//1
console.log(c);//3
let [a, [b], c] = [1, [2, 3], 4];
console.log(a, b, c);//1 //[2,3] //4
let [a, , [, b], c] = [1, 2, [3, 4, 5], 6];
console.log(a, b, c);// 出错
... 扩展运算符(展开数组、类数组) console.log(...[1, 2, 3, 4, 5]);
... 在结构语法中出现 表示的意思是剩余内容 剩余内容 返回的是一个数组 剩余内容 必须是最后一个变量
let [a, ...b] = [1, 2, 3, 4, 5];
console.log(a);
console.log(b);
let [a, ...b, c] = [1, 2, 3, 4, 5, 6]; //报错
let [a, ...b] = [1];
console.log(a);//1
console.log(b);//[] 空数组
function fn() {
let [a, b, c] = arguments;
console.log(a, b, c);
}
fn(5, 78, 3);//5 78 3
在结构语法中 允许为变量设置默认值
let [a, b = 7, c = 89] = [1];
console.log(a, b, c);
解构还可以用于对象
数组是有序的数据解构 解构时按序赋值 对象是无序的数据解构 无法按序赋值
在对象解构时 变量名必须与属性名相同
const obj = {
name: 'zhangsan',
age: 20,
sex: 'nan'
}
let { name, age, sex } = obj;
console.log(name);
console.log(age);
console.log(sex);
//出错 因为对象是无序的
const { random } = Math; //Math.random()
console.log(random());
const obj2 = {
phone: 13666666666,
...obj // 对象允许在另外一个对象中展开
}
console.log(obj2);//两个对象的结合...
字符串解构
let [a, b, c, ...d] = '123456789';
console.log(a, b, c, d);
模板字符串
模板字符串(template string) 一种字符串的新语法 本质上和普通字符串一样 没有区别 使用了不同的符号和变量的拼接方式
模板字符串使用反引号(``)
- 模板字符串 保留字符串书写时的格式 类似于 HTML 标签
- 允许在字符串中进行换行
- 使用了更方便的变量拼接方式
在模板字符串中 拼接变量使用 ${ }
在${ }中也可以使用表达式
let str = `你好
世界`;
console.log(str);
let message = '今天天气不太好';
console.log(`这里是一个模板字符串 我想说的是${message}`);
let age = 15;
console.log(`你好我今年${age}岁,我是${age >= 18 ? '成年人' : '未成年人'},再过${18 - age}年就成年了`);
//-------------------------------------
window.onload = function () {
let list = document.querySelector('#list');
let template = '';
for (let i = 0; i < 10; i++) {
template += `<li>
<a href="javascript:;">item ${i + 1}</a>
</li>`;
}
list.innerHTML = template;
}
严格模式www.rootbk.cn/?p=39)
严格模式 ES5 引入语言标准
- 未来消除JavaScript一些语法的不合理 不严谨问题 减少怪异行为
- 消除代码运行的一些不安全之处 保证代码的运行安全
- 提高编译器效率 加快运行速度
- 给未来的JavaScript版本过度进行铺垫
use strict; 进入严格模式 低版本浏览器不支持严格模式 会将这条语句当做普通字符串进行忽略 在开启严格模式之前 不允许有任何个代码(注释除外)
在严格模式中 变量必须先声明后使用
a = 10;
console.log(a);
在严格模式中 全局函数 不在拥有this指向(不在指向window)
function fn() {
console.log(this);
}
fn();
在严格模式中 任何eval进行的命令操作 都会报错
let eval = '123';
console.log(eval);
全局函数 eval() 作用是将一个字符串作为JavaScript代码进行解析
var str = 'var a = 5;var b = 6;console.log(a+b);';
eval(str);
在严格模式中 eval拥有独立的作用域(不会造成变量泄漏)
var str = '1+2*3-4+5';
console.log(eval(str));
console.log(a);
console.log(b);
在严格模式中 八进制将被禁用
console.log(010);
在严格模式中 callee 被禁用
function fn() {
console.log(arguments.callee);
}
fn();
十五、正则表达式
它是中立于 语言和平台的 一种用于描述字符规则的表达式
在EMCAScript中 它是内置对象 ECMAScript 为正则表达式提供了构造函数
RegExp 正则表达式 是 引用数据类型 它由 普通字符 和 特殊字符组成 用于 验证格式 匹配文本 文本查找 文本替换 ...
在正则中有一些符号具有特殊含义 不能直接使用 需要转义使用
. \ / * ? + ( ) [ ] { } ^ | $
转义符 \
\ ( $
正则表达式的创建
-
构造函数创建
let reg = new RegExp(string[,prop]);
参数 string 用于描述字符规则的字符串
prop 正则表达式修饰符
let reg = new RegExp('abc');
console.log(reg);
console.log(typeof reg);
- 字面量创建
let reg2 = /abc/;
console.log(reg2);
console.log(reg === reg2);
test()
RegExp.prototype.test()
语法: reg.test(string);
参数: string 用于检测的字符串
描述: test方法将检测一个字符串是否符合正表达式reg的匹配规则
返回值: boolean
let reg = /abc/;
let str = 'asdsa1bcasd23';
console.log(reg.test(str));//false
字符集
字符集
在正则中 [] 表示字符集
每一个字符集表示匹配中括号中的单个字符
每一个中括号表示 一个字符
^ 出现在字符集中 表示 非
^ 必须出现在字符集开始的位置
[0-9] 匹配一个数字
[a-z] 匹配一个小写字母
[A-Z] 匹配一个大写字母
[^0-5] 匹配除0-5之外的任意字符
[A-Za-z] 匹配一个大小写字母
[A-z] 匹配A-z范围内的askii编码
[A-Za-z0-9_] 匹配 字母,数字,下划线
预定义字符集
预定义字符集
预先设计好的 字符集
\d 匹配一个数字 等同于 [0-9]
\D 匹配一个非数字 等同于 [^0-9]
\w 匹配字母,数字,下划线 等同于 [A-Za-z0-9_]
\W 匹配非 字母,数字,下划线 等同于 [^A-Za-z0-9_]
\s 匹配一个空白符(空格 制表符)
\S 匹配一个非空白符(空格 制表符)
. 匹配除回车换行(\r\n)外的任意字符
匹配数量
匹配数量
匹配数量指的是 字符出现的次数
n? 表示字符出现0次或1次
n+ 表示字符出现1次或多次
n* 表示字符出现0次或多次
n{x} 表示字符出现x次
n{x,y} 表示字符出现x至y次
n{x,} 表示字符出现至少x次
匹配边界
匹配边界
^ 匹配边界开始
$ 匹配边界结束
\b 匹配单词边界
示例
let reg = /^(+86)?1[3-9]\d{9}$/; // 验证手机号的有效性
// 验证邮箱有效性
// 用户名@域名.顶级域名
// zhangsan@163.com
// 123456@qq.com
// xiaoming@jd.com
// xiaofen@tom.org
// root@roobk.cn
let email = /^\w{4,16}@[A-Za-z0-9]{2,}.[A-Za-z]{2,}(.[A-Za-z]{2,})?$/;
选择和分组
( ) 表示分组 一个圆括号表示一组内容 可以看作是一个整体
| 表示选择 类似于JS中逻辑或
正则表达式属性
正则表达式 在创建时 可以添加 匹配属性
正则表达式属性(修饰符)
global 全局匹配 修饰符 g
ignoreace 忽略大小写 修饰符 i
断言
正则表达式的断言
断言的组之一是边界
对于文本、词或模式,边界可以用来表明它们的起始或终止部分( 向前断言、向后断言以及条件表达式 )
捕获分组
RegExp.$$1 - $9
所以的 小括号() 按照左括号的出现顺序 进行分组 这种分组叫做 捕获分组
let reg = /(a(b))(c)/;
三个分组
a(b)
b
c
let reg = /(a(b))(c)/;
let str = 'abc';
let result = reg.test(str);
console.log(result);
console.log(RegExp.$1);
console.log(RegExp.$2);
console.log(RegExp.$3);
console.log(str.match(reg));
向前断言(?=)
x(?=y) 向前断言(正向前瞻匹配): x 被 y 跟随时 匹配 x 。
非捕获匹配
let reg = /Java(?=Script)/;
let str = 'JavaScript is fun';
console.log(reg.test(str));
console.log(str.match(reg));
console.log(RegExp.$1);
向前否定断言(?!)
x(?!y) 向前否定断言(反向前瞻匹配): x 没有被 y 紧随时 匹配 x 。
非捕获匹配
let reg2 = /Windows (?!2000|98|2003)/;
let str2 = '我使用的操作系统是 Windows 10';
console.log(reg2.test(str2));
console.log(str2.match(reg2));
console.log(RegExp.$1);
匹配但不捕获(?:)
(?:X) 表示匹配x 但是不记录捕获的值 非捕获匹配
let reg3 = /(?:123)/;
let str3 = 'aaaaaa123aaa';
console.log(reg3.test(str3));
console.log(str3.match(reg3));
console.log(RegExp.$1);
十六、PHP
php是用于web后端开发的 弱类型脚本语言 语法和JavaScript 非常相近 所有php文件都必须放在服务器环境(Apache)中运行
有非常严格的语法规范 语句的结尾必须带分号(;)结束
响应头
设置响应头(告诉浏览器 我们的内容是什么类型)
header('content-type:text/html;charset=utf-8');
输出语句
echo 语句 用于输出字符串
echo '你好世界';
echo '<br>';
echo '<h1>hello world</h1>';
变量定义
php 是一个弱类型脚本语言 弱类型 指的是 语言的变量 数据类型没有约束(变量可以保存任意类型的数据) 变量的数据类型 是由 赋值操作决定的(不是由声明决定的) 变量命名 使用驼峰命名法
JavaScript 变量声明 使用 var let const
在php中变量的声明没有关键字 直接对变量名进行赋值即可 php中所有的变量都是以 '$' 开头的
$userName = '张三';
$str = '你好';
$age = 20;
$price = 15.6;
$n = null;
$b = true;
'.' 运算符 在php中是 字符连接符(相当于js中的+)
echo $userName.'你好';
在php中 字符串类型 可以是单引号或双引号 单双引号是有区别的
双引号中可以识别变量(效果类似于JS中的模板字符串)
echo '<br>';
echo "你好我是$userName 今天天气真好";
查看数据类型
使用函数 var_dump() 可以查看数据类型
var_dump($str);
echo '<br>';
var_dump($age);
echo '<br>';
var_dump($price);
echo '<br>';
var_dump($n);
echo '<br>';
var_dump($b);
echo '<br>';
数组不能使用echo输出 可以使用 var_dump() 或 print_r()
$arr = [1,2,3,4,5];
var_dump($arr);
print_r($arr);
分支
if-else
$age = 15;
if($age >= 18){
echo '成年人';
}else{
echo '未成年人';
}
switch-case
$level = 2;
switch($level){
case 1:
echo 1;
break;
case 2:
echo 2;
break;
case 3:
echo 3;
//break; //依然会穿透
default:
echo 0;
}
循环
while
$i = 0;
while($i<10){
echo $i;
$i++;
}
do-while
do{
echo 'do-while';
}while(false);
for
for($i = 0;$i < 5;$i++){
echo $i.'<br>';
}
函数
php 的函数 函数名 没有$ 函数语法于JS相同
function myFunction(){
echo '我的函数';
}
myFunction();
function fn($num){
for($i = 2;$i<$num;$i++){
if($num % $i == 0){
return false;
}
}
return true;
}
if(fn(8)){
echo '是质数';
}else{
echo '不是质数';
}
数组
php数组有两种使用方式
- 索引数组
- 关联数组
php数组api文档
索引数组
数组中元素是有序排列
数组中的成员允许是任意数据类型
每一个元素都拥有一个索引值(index)
最小索引是0 最大索引为数组元素数量-1
不同于JS的是 php中的数组 没有length 属性
$arr = array(1,2,3,4,5);
print_r($arr);
查看数组中元素的个数 使用 count() 函数
echo count($arr);
遍历数组
for($i = 0; $i < count($arr) ;$i++){
echo $arr[$i];
}
//foreach 类似于JS中的 for-of
foreach($arr as $value){
echo $value.'<br>';
}
关联数组
关联数组 在php中是一种特殊的数据结构 它的本质是一种哈希结构(hash) 哈希结构指的是 使用 键值对的形式来保存数据
php的关联数组 表现类似于 JS中的对象
$user = array(
'username'=>'xiaowang',
'age'=>18,
'sex'=>'nan'
);
var_dump($user);
关联数组可以转换成json格式 JSON(JavaScript对象简谱)
将关联数组转换成JSON字符串(外层单引号内层双引号)
json_encode()
$str = json_encode($user);
echo $str;
将JSON字符串转换成对象
json_decode()
$obj = json_decode($json);
var_dump($obj);
混合二维数组
内层数组 关联数组 外层数组 索引数组
[{},{},{},{}]
header('conetent-type:application/json;charset=utf-8');
$data = array(
array(
'product'=>'iphone13',
'price'=>9988,
'color'=>'blue'
),
array(
'product'=>'iphoneX',
'price'=>6999,
'color'=>'black'
),
array(
'product'=>'xiaomi12',
'price'=>4999,
'color'=>'blue'
),
array(
'product'=>'huaweiP40',
'price'=>7777,
'color'=>'black'
),
);
var_dump($data);
$json = json_encode($data);
echo $json;
数据库
连接数据库
创建数组存入数据库基本信息
$mysql_conf = array(
'host'=>'localhost:3306', // 主机名和端口号 3306是mysql的默认端口号
'db_user'=>'root', // 登录数据库的用户
'db_pass'=>'root', // 登录密码
'db'=>'h5_2202' // 数据库名
);
登录(连接)数据库
$mysql = @new mysqli($mysql_conf['host'],$mysql_conf['db_user'],$mysql_conf['db_pass']);
判断连接是否出现错误
if($mysql->connect_errno){
// die 用于结束代码执行
die('连接错误'.$mysql->connect_errno); // 获得错误信息
}
设置查询字符集
$mysql->query('set names utf8');
选择数据库
$selected = $mysql->select_db($mysql_conf['db']);
判断是否成功选择数据库
if(!$selected){
die('数据库选择错误'.$mysql->error);
}
16.9.2 执行sql语句
执行sql语句 使用 query 函数 sql);
$sql = 'select * from users';
// 使用query进行查询操作 查询获得一个结果集对象
$results = $mysql->query($sql);
16.9.3 fatch_assoc()
fetch_assoc() 函数 从结果集中获得一条数据
$row = $results->fetch_assoc();
var_dump($row);
$row = $results->fetch_assoc();
var_dump($row);
$row = $results->fetch_assoc();
var_dump($row);
$row = $results->fetch_assoc();
var_dump($row);
转换为JSON字符串
$arr = array();
// 当循环条件是 一个函数调用的返回值赋值给一个变量时 循环条件为变量值
while($row = $results->fetch_assoc()){
// 将关联数组放入到索引数组 组成一个混合二维数组 (外层索引 内层关联)
array_push($arr,$row);
}
$json = json_encode($arr);//将关联数组转换成JSON字符串
echo $json;
16.10 cookie
cookie 是网站的 会话跟踪技术 会话 指的是 用户访问网站到关闭浏览器的过程 cookie 是浏览器 和 服务器 进行数据共享的一种技术
必须在服务器环境下使用
cookie信息会随http请求一起发送 它会在http请求报文的请求头(request header)中进行发送
浏览器端使用cookie document.cookie
cookie存储的数据是键值对形式 key=value 都是==字符串类型== 语法: document.cookie = 'key=value';
window.onload = function () {
let username = document.querySelector('#username');
let setcookie = document.querySelector('#setcookie');
let getcookie = document.querySelector('#getcookie');
setcookie.onclick = function () {
document.cookie = `username=${username.value}`;
}
getcookie.onclick = function () {
// console.log(document.cookie);
let [key, value] = document.cookie.split('=');
console.log(key, value);
}
}
setcookie.onclick = function () {
document.cookie = `username=${username.value}`;
}
getcookie.onclick = function () {
// console.log(document.cookie);
let [key, value] = document.cookie.split('=');
console.log(key, value);
}
}
16.10.1 多条数据存取
window.onload = function () {
let set = document.querySelector('#set');
let get = document.querySelector('#get');
set.onclick = function () {
// 设置多条cookie数据
// 多次对 document.cookie 进行赋值
document.cookie = 'username=lisi';
document.cookie = 'age=18';
document.cookie = 'sex=nan';
document.cookie = 'phone=13688888888';
document.cookie = 'email=lisi@163.com';
}
get.onclick = function () {
// console.log(document.cookie);
// 获得的cookie数据是一个字符串
// 多条cookie数据 默认使用 '; ' 进行分割
// 需要自行拆分
let cookies = document.cookie.split('; ');
// console.log(cookies);
// cookies = cookies.map((el) => {
// let [key, value] = el.split('=');
// return { key, value };
// });
cookies = cookies.reduce((obj, current) => {
let [key, value] = current.split('=');
obj[key] = value;
return obj;
}, {});
console.log(cookies);
}
}
16.10.2 生存期
cookie 默认生存期(有效期) 为 一次会话 cookie 的生存期是可以设置的 我们可以为 每一条cookie数据 单独去设置生存期
生存期是cookie 的一个属性 expires
expires 使用标准时间格式 表示cookie失效的时间
let get = document.querySelector('#get');
let set = document.querySelector('#set');
set.onclick = function () {
et d = new Date();
d.setDate(d.getDate() + 1);
document.cookie = 'message=你好世界;expires=' + d;
}
16.10.3 销毁cookie
销毁cookie的方式
- 将当前需要销毁的数据设置成空字符串 将key和value中的 value设置成 ''
- 将一个cookie的生存期设置成一个已过期的时间(-1)
document.cookie = 'message="";expires=-1';
16.10.4 cookie 路径
使用cookie时 需要注意路径对cookie的影响
在外层路径中设置的cookie 可以在内层路径中访问 在内层路径中设置的cookie 不可以在外层路径中访问
cookie的使用 有 作用域(路径的关系)
cookie的路径是可以设置的 使用 path 属性进行设置 document.cookie = 'key=value;path=/'; (/) 表示根目录
document.cookie = 'username=zhangsan';
console.log(document.cookie);
16.10.5 cookie 封装
'use strict';//严格模式
const cookie = {
get(key) {
if (document.cookie) {
let cookies = document.cookie.split('; ');
cookies = cookies.reduce((obj, curr) => {
let [key, value] = curr.split('=');
obj[key] = value;
return obj;
}, {});
if (key in cookies) {
return cookies[key];
}
}
return null; // 没有cookie返回null
},
set(key, value, expires, path = '/') {
if (Number.isInteger(expires)) {
let d = new Date();
d.setDate(d.getDate() + expires);
document.cookie = `${key}=${value};expires=${d};path=${path}`;
} else {
document.cookie = `${key}=${value};path=${path}`;
}
return this; // 让函数支持链式调用
},
remove(key, path = '/') {
this.set(key, '', -1, path);
return this;
}
};
十七、AJAX
Ajax技术诞生于2007年 异步的JavaScript 和 XML 传统的 Ajax技术 使用XML进行数据的封装 使用JS(DOM)进行数据的解析 现在的 Ajax技术 使用JSON对数据进行封装 使用对象的语法对数据进行解析
Ajax 核心对象 XMLHttpRequest
Ajax 提供了 异步发送请求的能力
发送请求的方式 表单 | get/post 跳转页面 href | get 跳转页面 Ajax | get/post 不跳转页面
Ajax 对象 XMLHttpRequest Ajax 实例方法 open(请求方式,请求路径[,异步]) 建立连接 setRequestHeader(请求头,值) 请求头设置 send([数据]) 发送请求
Ajax 实例属性 readystate ajax对象的准备状态(0-4) 4表示读取响应结束 onreadystatechange 事件 当就绪状态发生改变时 触发该事件(一共触发三次 当就绪状态为 2 3 4 时触发) status http状态码 200 服务器响应正常 responseText 获得响应文本
http 状态码 反应当前请求的状态信息 1xx 消息(信息) 101表示信息(Socket通信) 2xx 成功 200表示正常 3xx 重定向 304数据已缓存(协商缓存) 4xx 客户端错误 401认证失败(没登录) 403没有权限 404路径错误 5xx 服务端错误 500后端出错
17.1 ajax-get
ajax 使用需要发送请求 在服务器环境使用
使用ajax发送GET请求 一共有四个步骤
- 获得ajax对象的实例 XMLHttpRequest
- 使用open 建立连接
- 使用send 发送请求
- 设置事件 处理数据
const xhr = new XMLHttpRequest();
xhr.open('get', './2.json');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
const json = JSON.parse(xhr.responseText);
console.log(json[0].username);
// 传统xml请求 已经被淘汰
// let doc = xhr.responseXML;
// for (let i = 0; i < doc.childNodes[0].children[0].children.length; i++) {
// console.log(doc.childNodes[0].children[0].children[i].textContent);
// }
}
}
<?php
include('./library/conn.php'); // 连接数据库
$username = $_REQUEST['username']; // 接收前端发送的用户名
$select = "select * from users where username='$username'";
$res = $mysql->query($select);
$mysql->close();
if($res->num_rows>0){
echo '{"message":"用户名已存在","username":"'.$username.'","has":true,"success":1}';
}else{
echo '{"message":"用户名可以使用","username":"'.$username.'","has":false,"success":1}';
}
// 接口文档
// request url: ./interface/hasuser.php
// request method: get
// parames: username(string)
// response: json
?>
17.2 ajax-post
ajax 使用需要发送请求 在服务器环境使用
使用ajax发送POST请求
- 获得ajax对象的实例 XMLHttpRequest
- 使用open 建立连接
-
- post请求需要设置请求头 在发送请求之前
- post的数据 是随请求头(request header/request body)的 请求体(request body)发送
- 使用send 发送请求
- 设置事件 处理数据
get 请求的数据 放在请求头(request header) 数据在 url的 search 部分 post请求的数据 放在 send函数的参数中
let username = document.querySelector('#username');
let message = document.querySelector('#message');
username.oninput = function () {
const xhr = new XMLHttpRequest();
xhr.open('post', './interface/hasuser.php');
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded;charset=utf-8');
// application/x-www-form-urlencoded 表单格式数据
// 'name=value&name=value&name=value'
xhr.send(`username=${this.value}`);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
message.innerHTML = data.message;
message.className = data.has ? 'red' : 'green';
}
}
}
17.2 ajax-json
let username = document.querySelector('#username');
let message = document.querySelector('#message');
username.oninput = function () {
const xhr = new XMLHttpRequest();
const data = {
username: this.value
}
xhr.open('post', './interface/hasuser-json.php');
xhr.setRequestHeader('content-type', 'application/json;charset=utf-8');
// application/josn JSON数据格式(字符串)
// '{"key":"value","key":"value"}'
xhr.send(JSON.stringify(data));
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
const data = JSON.parse(xhr.responseText);
message.innerHTML = data.message;
message.className = data.has ? 'red' : 'green';
}
}
}
<?php
include('./library/conn.php'); // 连接数据库
$data = file_get_contents('php://input'); // 接收JSON数据的
$obj = json_decode($data);
$username = $obj->username;
$select = "select * from users where username='$username'";
$res = $mysql->query($select);
$mysql->close();
if($res->num_rows>0){
echo '{"message":"用户名已存在","username":"'.$username.'","has":true,"success":1}';
}else{
echo '{"message":"用户名可以使用","username":"'.$username.'","has":false,"success":1}';
}
// 接口文档
// request url: ./interface/hasuser.php
// request method: get
// parames: username(string)
// response: json
?>
17.3 封装ajax
// $.get(url,data,dataType);
// $.post(url,data,dataType);
const $ = {
get(url, data, dataType) {
// 在地址上加上一个时间戳 保证每一次的请求是不一样的 避免获得缓存内容(304)
url += "?_=" + Date.now();
if (typeof data === 'object' && data !== null) {
for (let key in data) {
// 拼接url
url += `&${key}=${data[key]}`;
}
}
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
if (dataType === 'json') {
resolve(JSON.parse(xhr.responseText));
} else {
resolve(xhr.responseText);
}
}
setTimeout(() => {
reject(new Error('请求超时'));
}, 3000);
}
});
},
post(url, data, dataType) {
return new Promise((resolve, reject) => {
let dataString = '';
if (typeof data === 'object' && data !== null) {
// 将数据处理成表单数据结构
// name=value&name=value
for (let key in data) {
dataString += `${key}=${data[key]}&`;
}
dataString = dataString.slice(0, -1);
}
const xhr = new XMLHttpRequest();
xhr.open('post', url);
xhr.setRequestHeader('content-type', 'application/x-www-form-urlencoded;charset=utf-8');
xhr.send(dataString);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
if (dataType === 'json') {
resolve(JSON.parse(xhr.responseText));
} else {
resolve(xhr.responseText);
}
}
setTimeout(() => {
reject(new Error('请求超时'));
}, 3000);
}
});
}
};
$.get('./interface/hasuser.php', { username: 'root', age: 20, sex: 'nan' }, 'json')
.then(val => {
console.log(val);
}).catch(err => {
console.error(err);
});
$.post('./interface/hasuser.php', { username: 'lisi2', age: 20, sex: 'nan' }, 'json')
.then(val => {
console.log(val);
}).catch(err => {
console.error(err);
});
17.4 JSONP
JSONP
JSONP 和 JSON 毫无关系
它诞生于 社区 -> 没有官方标准(也不是语言标准) 它是主流的跨域解决方案之一
JSONP 合理的使用了一些浏览器的安全漏洞进行数据请求(卡BUG)
在浏览器中 任何的资源加载 都是HTTP请求(GET请求) 图片 音频 视频 CSS JS HTML ...
有一个不受同源策略限制的属性 src 拥有src属性的元素 img script iframe
JSONP 使用的是 script 元素 进行 get 数据请求 script 元素的作用 引入并执行JavaScript (bug) 它会将所请求到的任何内容 都当做JavaScript来执行
<script src="./interface/abc"></script>
<script src="./interface/123.txt"></script>
<img src="https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png" alt="">
<iframe src="https://www.sina.com.cn" frameborder="0"></iframe>
JSONP 的使用流程
- 使用JavaScript 动态创建script元素
- 将需要请求的地址 放入script元素的 src 属性
- 将script元素放入页面
- 处理结果
window.onload = function () {
let script = document.createElement('script');
script.src = './interface/1.txt';
document.body.appendChild(script);
}
function fn(data) {
console.log(data);
}
十八、Promise
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。 它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。 从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。 Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
Promise对象有以下两个特点。
(1)对象的状态不受外界影响。 Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。 只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。 这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。 Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。 只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。 如果改变已经发生了,你再对Promise对象添加回调函数,也会立即得到这个结果。 这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
console.log(1);
let p = new Promise((resolve/* 成功 */, reject /* 失败 */) => {
// 这个回到函数 是Promise容器
// 用来存放一个异步操作
// 但是这个容器本身是同步执行的
// console.log(2);
// ------------------------------------------
// 参数 resolve 和 reject 用于改变Promise状态
// Promise的状态改变有两种可能性
// 1. pendding变成fulfilled 进行中变成已成功
// 2. pendding变成rejected 进行中变成已失败
resolve(); // 将状态改变成fulfilled
reject(); // 将状态改变成rejected
});
// console.log(3);
console.log(p);
// resovle 和 reject 中的参数 会成为 PromiseResult
let p2 = new Promise((resolve, reject) => {
let num = 31;
if (Number.isInteger(num)) {
resolve('num是整数');
} else {
reject('num不是整数');
}
});
// console.log(p2);
18.1 then() & catch()
Promise.prototype.then()
Promise.prototype.catch();
当promise的状态发生改变后 状态变成 fulfilled 会执行实例的then函数 resolve中的实参会传递给then作为回调函数的形参 状态变成 rejected 会执行实例的catch函数 reject中的实参会传递给catch作为回调函数的型参
then 和 catch 是异步的
console.log(1);
p2.then(result => {
console.log(2);
console.log(result, '成功');
}).catch(result => {
console.log(3);
console.log(result, '失败');
});
console.log(4);
then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。 因此可以采用链式写法,即then方法后面再调用另一个then方法。
const p = new Promise((resolve, reject) => {
resolve(123);
});
p.then(value => {
console.log(value);//123
return value + 10;
}).then(value => {
console.log(value);//133
return value + 1;
}).then(value => {
console.log(value);//134
});
试题:将 no,zuo,no,die变成 No Zuo No Die
const p2 = new Promise((resolve, reject) => {
// reject('ok');
resolve('no,zuo,no,die'); // -> No Zuo No Die
});
p2.then(value => value.split(','))
.then(value => value.map(el => el[0].toUpperCase() + el.slice(1)))
.then(value => value.join(' '))
.then(value => console.log(value));
当then函数中拥有两个回调函数 第一个回调函数 表示成功时执行 第二个回调函数 表示失败时执行
p2.then((val) => {
console.log(123);
}, (val) => {
console.log(val);
console.log(456);
});
// p2.then().catch() 推荐语法
18.2 finally()
Promise.prototype.finally() finally()方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。
finally中的代码是异步代码
console.log(1);
p2.then(val => {
console.log(2);
console.log(val);
}).catch(err => {
console.log(err);
}).finally(() => {
console.log(3);
console.log('ok1');
});
console.log(4);
//1 4 2 3 ok1
18.3 all()
静态方法 Promise.all() Promise.all() 将多个 Promise的实例 包装成一个新的Promise实例
语法: Promise.all([promise,...promise]); 接收一个数组或类数组对象作为参数 数组中每一个元素都是promise实例 如果有不是Promise实例的 则自动调用 Promise.resolve() 将其转换成promise实例
Promise.all() 创建的这个新Promise对象 状态取决于 传入的数组中每一个Promise结果 当所有Promise的状态都为 成功 则 新Promise的状态为 成功 在then可以获得到所有的成功结果(数组) 当参数中有Promise的状态为 失败 则 新Promise的状态为 失败 在catch中可以获得第一个失败的结果
const p1 = new Promise((resolve, reject) => {
reject(111);
});
const p2 = new Promise((resolve, reject) => {
reject(222222);
});
const p3 = new Promise((resolve, reject) => {
resolve(3333333);
});
const p4 = new Promise((resolve, reject) => {
resolve(444444444);
});
const p5 = Promise.all([p1, p2, p3, p4]);
p5.then(val => {
console.log(val, 1);
}).catch(err => {
console.log(err, 2); //111,2
})
18.4 resolve() & resreject()
Promise.resolve() 将一个对象转换成 Promise实例 并且将状态改变为 成功
Promise.reject() 将一个对象转换成 Promise实例 并且装状态改变为 失败
let str = 'abc';
let p = Promise.resolve(str);
p.then(val => {
console.log(val);
});
let p2 = Promise.reject(str);
p2.then().catch(val => {
console.log(val);
});
18.4 promise-ajax
const ajax = new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('get', './interface/hasuser1.php?username=zhangsan1');
xhr.send();
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(xhr.responseText);
}
setTimeout(() => {
reject(new Error('请求超时'));
}, 3000);
}
});
ajax.then(data => {
console.log(data);
}).catch(err => {
console.error(err);
});
十九、Bootstrap
19.1 基本模板
<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>基本模板</title>
<link rel="stylesheet" href="./bootstrap/css/bootstrap.min.css">
</head>
<body>
<script src="./bootstrap/js/jquery.js"></script>
<script src="./bootstrap/js/bootstrap.min.js"></script>
</body>
</html>
19.2 栅格系统
v3.bootcss.com/css/ 栅格系统 栅格系统是由 bootstrap 首创的 一套响应式布局解决方案 采用了表格的兼容性特点 浮动布局的灵活性 通过媒体查询 实现响应式布局 栅格系统 采用 浮动的方式进行布局 模拟表格
基本布局容器
1. container 定宽容器(宽度固定)
2. container-fluid 流式容器(宽度自适应 100%)
在文档中可以查看 bootstrap 将页面的分类情况
bootstrap3 中 页面被划分成了4种不通的尺寸
container宽度
大屏幕 浏览器宽度>=1200px lg 1170px
中等屏幕 浏览器尺寸>=992px md 970px
小屏幕 浏览器尺寸>=768px sm 750px
超小屏幕 浏览器尺寸<768px xs aoto(100%)
<div class="container">
<!-- 栅格系统以行为单位进行布局 使用类名 row -->
<!-- bootstrap3 将每一行进行了 12等分 -->
<div class="row">
<!-- col-*-x 表示单元格 *表示浏览器尺寸名称 x表示所占比例(1-12) -->
<!-- col-lg-4 表示 当前单元格在 大屏幕尺寸下 占比 4/12 -->
<div class="col-lg-4 col-md-6 col-sm-8 col-xs-12" style="background:red;">你好世界</div>
<div class="col-lg-8 col-md-6 col-sm-4 col-xs-12" style="background:blue;">你好世界</div>
</div>
<div class="row">
<div class="col-lg-1" style="border:1px solid black">0001</div>
<div class="col-lg-1" style="border:1px solid black">0002</div>
<div class="col-lg-1" style="border:1px solid black">0003</div>
<div class="col-lg-1" style="border:1px solid black">0004</div>
<div class="col-lg-1" style="border:1px solid black">0005</div>
<div class="col-lg-1" style="border:1px solid black">0006</div>
<div class="col-lg-1" style="border:1px solid black">0007</div>
<div class="col-lg-1" style="border:1px solid black">0008</div>
<div class="col-lg-1" style="border:1px solid black">0009</div>
<div class="col-lg-1" style="border:1px solid black">0010</div>
<div class="col-lg-1" style="border:1px solid black">0011</div>
<div class="col-lg-1" style="border:1px solid black">0012</div>
</div>
<div class="row">
<!-- hidden-* 隐藏 -->
<div class="col-lg-5 col-md-6" style="background-color: #666;">
<div class="row">
<div class="col-lg-6" style="background-color: chocolate;">11111111</div>
<div class="col-lg-6" style="background-color: crimson;">222222222222</div>
</div>
</div>
<div class="col-lg-2 hidden-md" style="background-color: aqua;">222222</div>
<div class="col-lg-5 col-md-6" style="background-color: blueviolet;">333333333333333</div>
</div>
</div>
19.3 全局样式
<span class="center-block text-center">你好世界</span>
<div class="text-center h2">你好世界</div>
<div class="text-center h2 text-primary bg-info">你好世界</div>
<div class="text-center h2 text-danger bg-success">你好世界</div>
<div class="text-center h2 text-info bg-danger">你好世界</div>
<div class="text-center h2 text-warning bg-primary">你好世界</div>
<div class="text-center h2 text-success bg-warning">你好世界</div>
<a class="btn btn-default">按钮</a>
<button class="btn">按钮</button>
<button class="btn btn-default">按钮</button>
<button class="btn btn-success btn-xs">按钮</button>
<button class="btn btn-danger btn-lg">按钮</button>
<button class="btn btn-warning btn-sm">按钮</button>
<button class="btn btn-info" disabled>按钮</button>
<button class="btn btn-primary btn-block">按钮</button>
<div class="text-right">我是文本</div>
<span class="caret"></span>
二十、 JQuery
jquery.cuishifeng.cn/index.html 具体看文档
20.1 工厂函数
jQuery 提供了一个工厂函数 用于创建对象(使用jQuery工厂函数创建的对象 都叫做 jQuery对象) jQuery 提供的工厂函数名称 jQuery 工厂函数的别名 $
console.log(jQuery);
console.log($);
console.log(jQuery === $);
window.jQuery = window.$ = jQuery;
jQuery中 封装了一些 DOM操作的功能 和 数据请求(ajax ,jsonp)的功能
20.2 就绪事件
就绪事件 window.onload = function(){} document.addEventListener('DOMContentLoaded',function(){});
jQuery 中 也提供了就绪事件 jQuery 3 提供的就绪事件 是 DOMContentLoaded
jQuery提供的就绪事件 jQuery.ready(funciton(){})
完整写法 (function(){})
$(document).ready(function () {
let btn = document.querySelector('#btn');
console.log(btn);
});
$(function () {
let btn = document.querySelector('#btn');
console.log(btn);
});
20.3 工厂函数基本语法
工厂函数的基本语法 (选择器).动作()
jQuery的工厂函数 主要作用是用于创建jQuery对象
- jQuery工厂函数是根据(CSS选择器)选择元素 将所有匹配的元素 包装成一个类数组对象(jQuery对象)
- 将指定的 对象、数组 包装成一个类数组对象(jQuery对象)
- 将指定的 类数组对象、DOM元素 包装成类数组对象(jQuery对象)
$(function () {
// console.log($('#btn')); // 替换 document.querySelectorAll()
// console.log($('button'));
// console.log($('.btn'));
let box1 = document.querySelector('.box1');
// console.log($('.btn', box1));
// console.log($('.btn', $('.box2')));
const o = { x: 1, y: 2 };
console.log($(o)); // 返回一个jQuery对象 索引0是对象o
const arr = [1, 2, 3, 4, 5];
console.log($(arr));
console.log($(box1));
});
20.4 元素选择
jQuery的基本语法 $(selector).action();
jQuery 支持所有的CSS和 CSS3选择器并且也扩充了一些选择器 jQuery 的元素选择功能 依赖于 第三方库 Sizzle.js
$('#list>li:first').css('color', 'red');
$('#list>li:last').css('color', 'red');
$('#list>li:not(:first,:last)').css('color', 'blue');
//:even :odd 指的是索引的偶数和奇数 从0开始 0是第一个索引
$('#list>li:even').css('color', 'blue');
$('#list>li:odd').css('color', 'yellow');
/* css中 奇数偶数的计算从1开始 */
/* #list>li:nth-child(even) {
color: red;
} */
$('#list>li:eq(3)').css('color', 'red');
$('#list>li:lt(3)').css('color', 'blue');
$('#list>li:gt(3)').css('color', 'pink');
$(':lang(en-us)').hide();
$('.Chinese').on('click', function () {
$(':lang(zh-cn)').show();
$(':lang(en-us)').hide();
});
$('.English').on('click', function () {
$(':lang(zh-cn)').hide();
$(':lang(en-us)').show();
});
$(':header').css('color', 'red');
20.5 事件
基本语法 $(selector).action()
$('.btn').mouseover(function () {
console.log('123', this);
});
20.6 事件监听
事件监听 $(selector).on(events,callback); 参数: events(string) callback(function)
$('.btn').on('click', function () {
console.log(this);
});
$('.box').on('mouseenter mouseleave', function (ev) {
// console.log(this); // this 在这是DOM对象
// .css() 是jQuery对象的方法
// this.css('background', 'red');
// $() 工厂函数 作用是创建jQuery对象
if (ev.type === 'mouseenter') {
// $(this) 将DOM对象包装成jQuery对象 -> DOM转jQuery
$(this).css('background', 'red');
} else {
$(this).css('background', 'green');
}
});
//------------------------------------------------------------
$('.box').hover(function (ev) {
console.log(ev.type);
$(this).css('background', 'yellow');
}, function (ev) {
console.log(ev.type);
$(this).css('background', 'red');
});
//--------------------------------------------------------------
$('.box').on({
mouseenter(ev) {
console.log(ev.type);
},
mouseleave(ev) {
console.log(ev.type);
},
click() {
console.log('点击事件');
}
});
//-------------------------------------------------------------------
$('.btn:first').on('click', function () {
alert(1);
});
$('.btn:first').on('click', function () {
alert(2);
// $('.btn:first').off('click'); // 移除了所有点击事件
$('.btn:first').off('click', arguments.callee);
});
20.7 事件委托
事件委托 将元素的事件处理函数 委托交给 元素的 父级或祖先级元素
事件处理周期
- 事件捕获 事件沿DOM树向下传播
- 目标触发 运行事件处理函数
- 事件冒泡 事件沿DOM树向上传播
事件委托 使用的是 事件冒泡的机制
事件委托的作用
- 给未来元素添加事件
- 减少DOM的查找次数
- 减少事件的绑定次数
jQuery 对事件委托进行了非常强的支持
$(function () {
// $('.box').on('click', '.btn', function (ev) {
// console.log(1);
// });
$('.box').on('click', 'button', function () {
// 创建元素
// let button = document.createElement('button');
// button.innerHTML = '按钮';
// box.appendChild(button);
// --------------------------------
// jQuery创建元素
// $('<button>按钮</button>');
// console.log($('<button class="newbtn">按钮</button>'));
$('.box').append($('<button class="newbtn">按钮</button>'));
});
// console.log($('#list>li'));
// $('#list>li').on({
// mouseover() {
// $(this).css('color', 'red');
// },
// mouseout() {
// $(this).css('color', '');
// }
// })
$('#list').on({
mouseover() {
$(this).css('color', 'red');
},
mouseout() {
$(this).css('color', '');
}
}, 'li');
$('#list').off('mouseout', '**');
});
20.8 事情派发一次性事件
一次性事件 $(selector).one(events,callback);
$('#btn').on('click', function () {
alert('运行了');
$(this).off('click', arguments.callee);
});
$('#btn').one('click', function () {
alert('运行了');
});
// ---------------------------------------------
$('#box').on('click', function () {
alert('我是box的点击事件');
});
$('#btn').on('click', function () {
// 事件派发(用于触发某个事件)
// $(selector).trigger(event);//切换隐藏或者显示
$('#box').trigger('click');
})
20.9 属性操作
$(selector).attr(name);
//获得第一个被选元素的 属性值 (node.getAttribute(name))
console.log($('#list>.item').attr('title'));
$(selector).attr(name,value);
//给所有被选元素 设置属性 (node.setAttribute(name,value))
$('.item').attr('title', 'hahaha');
const arr = [...$('#list>.item')];
const res = arr.map(el => $(el).attr('title'));
console.log(res);
//错误写法(当前代码有2次DOM查找) bad
$('.item').attr('class', 'contents');
$('.contents').attr('style', 'color:red');
//正确写法(只有一次DOM查找) good
let items = $('.item');
items.attr('class', 'contents');
items.attr('style', 'color:red');
//链式调用(只有一次DOM查找) best
$('.item').attr('class', 'contents').attr('style', 'color:red');
//$(selector).attr(options); best
//参数 options(object)
//对象的属性名为 元素的属性名
//对象的属性值为 元素的属性值
$('.item').attr({
'class': 'contents',
'style': 'color:blue'
});
$(selector).attr(name,callback); 在jQuery中 元素和属性操作 使用回调语法 是jQuery为我们遍历所有被选元素 回调参数 索引值 和 当前元素的属性值 回调中的返回值 会被设置成元素的属性值
$('#list>li').attr('class', function (i, elm) {
// console.log(i, elm);
return 'item' + (i + 1);
});
//------------------------------------------------
$('#list>li').attr({
'class': function (i, val) {
console.log(val);
},
'title': function (i, val) {
// console.log(val);
if (val) return 'hello world';
}
});
$(selector).removeAttr() 删除所有被选元素的属性
$('.item1').removeAttr('title');
$('#list>li[title]').removeAttr('title');
20.10 prop()
用于获得或设置隐藏的布尔属性
$(selector).prop();
$(function () {
// $(':checkbox').on('click', function () {
// console.log($(this).attr('checked')); // attr函数 无法获得 隐藏的布尔属性
// $(selector).prop(); 用于获得或设置隐藏的布尔属性
// console.log($(this).prop('checked'));
// });
const items = $(':checkbox:not(.allcheck)');
const allcheck = $('.allcheck');
allcheck.on('click', function () {
items.prop('checked', $(this).prop('checked'));
});
function isAllCheck() {
const elms = Array.from(items);
return elms.every(el => $(el).prop('checked'));
}
items.on('click', function () {
allcheck.prop('checked', isAllCheck());
});
});
20.11 css类名操作
$(selector).addClass(className); 给所有被选择元素添加类名
$(function () {
$('#btn').on('click', function () {
$('.box').addClass('red-1');
$('.box').addClass(function (index, current) {
// console.log(index, current);
return `red-${index + 1}`
});
});
});
$(selector).removeClass(className); 删除所有被选元素的指定类名
$('.box').removeClass('red-1');
$(selector).toggleClass(className); 给所有被选择元素 切换类名(如果元素有该类名则删除 没有则添加)
$('.box').toggleClass('red-3');
20.12 内容操作
$(selector).html(); 获得第一个被选元素的html内容 (innerHTML)
console.log($('.box').html());
$(selector).html('content') (innerHTML = )
//给所有被选元素设置html内容
$('.box').html('<span style="color:red">你好</span>');
$(selector).html(callback); (innerHTML += )
//给所有被选元素 设置、修改 html内容
$('.box').html(function (index, current) {
// console.log(index, current);
return current + '<h2>新内容</h2>';
});
$(selector).text(); 获得所有被选元素的文本 自动拼接字符串
console.log($('.box').text());
$(selector).text('content');
//给所有被选元素设置文本内容
$('.box').text('<h1>哈哈哈</h1>');
$(selector).text(callback);
$(selector).val() 获得第一个被选元素的value值 (node.value)
console.log($('input').val());
$(selector).val('value');
//给所有被选元素设置value (node.value=)
$('input').val('你好世界');
$(selector).val(callback); (node.value += )
$('input').val(function (index, current) {
return current + '你好世界';
});
20.13 效果
jQuery 内置了三组 动画效果 为所有动画效果 配备了三个时间预设值 'slow' 600ms 'normal' 400ms 'fast' 200ms
==隐藏/显示== (selector).show([timer,callback]); $(selector).toggle([timer,callback]);
==滑动效果== (selector).slideUp([timer,callback]); $(selector).slideToggle([timer,callback]);
==淡入淡出== (selector).fadeOut([timer,callback]); (selector).fadeTo([timer,opacity,callback]);
$('#btn').on('click', function () {
$('.box').hide(3000, function () {
alert('动画完毕');
});
$('.box').show(2000);
$('.box').toggle(2000);
$('.box').slideDown(2000);
$('.box').slideUp(2000, function () {
$('.box').slideDown(2000, function () {
$('.box').css('background', 'yellow');
});
});
$('.box').slideToggle(2000);
$('.box').fadeOut(2000);
$('.box').fadeIn(2000);
$('.box').fadeToggle(2000);
$('.box').fadeTo(2000, 0.6);
});
20.14 自定义动画
自定义动画 $(selector).animate(options,timer,callback); options(object) 用于存放css target timer(string/number) 动画时长 callback(function) 动画结束后的回调
自定义动画预设值 show hide toggle 宽高 透明度 适用
$('#btn').on('click', function () {
$('.box').animate({
// width: '200px',
// height: 500
// width: '+=100'
// top: 100,
// left: '-=100'
// width: 'toggle'
// opacity: 'toggle'
top: 200,
// left: 200,
// width: 300,
// height: 300,
// borderRadius: '50%'
}, 1000, function () {
alert('动画完成');
});
})
20.15 动画队列
jQuery的动画效果 包含了 hide/show/toggle/slideDown/slideUp/slideToggle/fadeIn/fadeOut/fadeTo/fadeToggle/animate jQuery 会位每一个元素 设置动画队列
队列是一种数据结构(先进先出) jQuery 为元素提供动画的队列支持 当元素的当前动画结束后才会开始执行下一个动画 为一个元素添加多个动画效果时 就会形成动画队列
jQuery所有动画效果 返回值 都是 jQuery对象 所以支持链式调用
在动画队列的任意位置 可以使用 delay() 函数 实现动画延迟
$('.box').on('click', function () {
$(this).slideUp(2000).delay(1000).fadeIn(3000).hide(2000);
$(this).animate({ width: 300 }, 1000)
.delay(2000)
.animate({ height: 300 }, 1000)
.delay(1000)
.animate({ width: 100 }, 1000)
.delay(3000)
.animate({ height: 100 }, 1000);
});
//如果使用数组来模拟队列
//数组只使用 push 和 shift 函数
[
{ type: 'animate', timer: 1000, prop: { width: 300 } },
{ type: 'delay', timer: 2000 },
{ type: 'animate', timer: 1000, prop: { height: 300 } },
{ type: 'delay', timer: 1000 },
{ type: 'animate', timer: 1000, prop: { width: 100 } },
{ type: 'delay', timer: 3000 },
{ type: 'animate', timer: 1000, prop: { height: 100 } },
]
});
20.16 停止动画
$(selector).stop(clearQueue,jumpToEnd);
clearQueue:如果设置成true,则清空队列。可以立即结束动画。
jumpToEnd:如果设置成true,则完成队列。可以立即完成动画。
$('.start').on('click', function () {
$('.box')
.animate({ width: 300 }, 1000)
.animate({ height: 300 }, 1000)
.animate({ width: 100 }, 1000)
.animate({ height: 100 }, 1000);
});
$('.stop1').on('click', function () {
// 停止当前正在执行的动画
// 不影响动画队列
$(':animated').stop();//false false
});
$('.stop2').on('click', function () {
// 停止当前正在执行的动画
// 清空动画队列
$(':animated').stop(true);//true false
});
$('.stop3').on('click', function () {
// 清空动画队列
// 立即完成动画
$(':animated').stop(true, true);
});
$('.stop4').on('click', function () {
// 不清空动画队列
// 立即完成动画
$(':animated').stop(false, true);
});
20.17 文档处理
20.17.1 append()
$(selector).append(); 参数: String,Element,jQuery 将参数追加每一个被选元素的结尾 (node.appendChild(childNode))
$('.box').append('<h1>你好世界</h1>');
$('.box').append(document.createElement('span'));
$('.box').append($('<a href="https://www.baidu.com">baidu</a>'));
$('.box').append($('h1'));
// -------------------------------------------
$('.box').append(function (i, currentHTML) {
return '<span style="color:red">new span ' + (i + 1) + '</span>';
});
20.17.2 prepend()
$(selector).prepend() 参数: String,Element,jQuery 将参数追加每一个被选元素的开头
$('.box').prepend('<h1>你好世界</h1>');
20.17.3 appendTo()
$(selector).appendTo(selector); 颠倒了append的参数
$('h1').appendTo($('.box'));
20.17.4 prependTo()
$(selector).prependTo(selector); 颠倒了prepend的参数
$('h1').prependTo($('.box'));
20.17.5 after()
$(selector).after() 参数: String,Element,jQuery 在被选元素之后插入内容
$('.box').after('<h1>hahaha</h1>');
20.17.6 before()
$(selector).before() 参数: String,Element,jQuery 在被选元素之前插入内容
$('.box').before('<h1>hahaha</h1>');
20.17.7 wrap()
$(selector).wrap() 使用一个元素结构包裹每一个被选元素
$('.box').wrap('<header class="h"></header>');
20.17.8 wrapAll()
$(selector).wrapAll() 使用一个元素 包裹所有被选元素
$('.box').wrapAll('<header class="h"></header>');
20.17.9 unwrap()
$(selector).unwrap() 取消wrap 效果 元素从父元素中取出(把被选元素的父元素删了)
$('.box').unwrap();
20.17.10 wraplnner()
$(selector).wrapInner() 内部包裹 包裹被选元素的子节点
$('.box').wrapInner('<span style="color:red"></span>');
20.17.11 replaceWith()
$(selector).replaceWith() 使用一个新的DOM结构 替换被一个被选元素
$('.box').replaceWith('<h1>你好世界</h1>');
20.17.12 remove()
$(selector).remove() 删除被选元素 不保留事件
$('h1').remove();
20.17.13 detach()
$(selector).detach() 删除被选元素 返回一个jQuery对象 包含了被删除的元素 detach删除的元素 如果有事件可以被保留
console.log($('h1').detach());
20.17.14 empty()
$(selector).empty(); 清空被选元素的子节点
$('.box').empty();
20.17.14 clone()
$(selector).clone() 复制一个被选元素 返回一个jQuery对象
$('.box').append($('h1').clone());
20.18 css
$(selector).css(style); 获得第一个 被选元素的 计算后样式
console.log($('.box').css('padding'));
$(selector).css(style,value); 给所有被选择的元素添加 行内样式(返回jQuery对象) 支持链式调用
$('.box').css('color', 'red').css('fontSize', '2em');
$(selector).css(options); 给所有被选择的元素添加 行内样式(返回jQuery对象) 支持链式调用
$('.box').css({
color: 'red',
fontSize: '3em'
});
$(selector).css(style,callback);
$('.box').css('width', function (i, current) {
// console.log(i, current);
return (i + 1) * 100 + 'px';
});
$('.box').css({
width(i, curr) {
return (i + 1) * 100 + 'px';
},
height(i, curr) {
return (i + 1) * 100 + 'px';
}
});
位置
offset() 在当前视口的相对偏移值
getBoundingClientReck() 获取页面中某个元素的左,上,右和下分别相对浏览器视窗的位置。
position() 相对于父级定位元素的偏移
console.log($('.box:first').offset()); // 获得第一个匹配元素 在当前视口的相对偏移值
console.log($('.box:first').position()); // 获得第一个匹配元素 相对于父级定位元素的偏移
尺寸
width() 元素的宽
innerWidth() 内容的宽(不包括边框) 该方法包含 padding
outerWidth() 元素的宽 包含 padding 和 border 如需包含 margin,请使用 outerWidth(true)
console.log($('.box:first').height(), $('.box:first').width());
console.log($('.box:first').innerHeight(), $('.box:first').innerWidth());
console.log($('.box:first').outerHeight(), $('.box:first').outerWidth());
20.21 过滤
//eq(index|-index) 意义是链式调用
$('#list>li').css('color', 'red').eq(4).css('color', 'blue');
$('#list>li').css('color', 'red').first().css('color', 'green');
$('#list>li').css('color', 'red').last().css('color', 'green');
$('#list>li').on('click', function () {
if ($(this).hasClass('item')) { // hasClass 返回布尔值
$(this).css('color', 'red');
}
});
$('#list>li').css('color', 'red').filter(':even').css('color', '#ccc');
$('#list>li').filter(function (i, elm) {
if ((i + 1) % 3 == 0) {
return elm;
}
}).css('color', 'red');
$('#list>li').on('click', function () {
$(this).is($('#list>li').first()) && $(this).css('color', 'red');
});
let result = $('#list>li').map(function (i, elm) {
return {
className: $(elm).attr('class') ? $(elm).attr('class') : null,
text: $(elm).text()
}
});
console.log(Array.from(result));
$('#list>li').has('b').css('color', 'red');
$('#list>li').not(':first,:last').css('color', 'red');
$('#list>li').slice(3, -2).css('color', 'red');
20.22 查找
$('.list').children('.item').css('color', 'red'); // 找子元素
$('.list>li:first').closest('ul').css('color', 'red'); //向上查找
$('button').closest('div').css('color', 'red');
$('.list').find('li.item').css('color', 'red'); // 找后代元素
$('.list>li').first().css('color', 'red').next().css('color', 'blue');
$('.list>li').first().css('color', 'red').nextAll().css('color', 'blue');
$('.list>li').first().css('color', 'red').nextUntil($('.list>li:eq(5)')).css('color', 'blue');
$('button').on('click', function () {
console.log($(this).offsetParent()); // 获得离他最近的定位过的元素 没有元素定位 则为html
});
console.log($('button').parent());//父辈
console.log($('button').parents());
console.log($('button').parentsUntil('.box1'));
$('.item:first').siblings('.item').css('color', 'red'); //兄弟姐妹们(不包括自己)
二十一、面向对象编程(面向对象程序设计)
一种计算机编程架构
面向对象程序设计(Object Oriented Programming)作为一种新方法,其本质是以建立模型体现出来的抽象思维过程和面向对象的方法。模型是用来反映现实世界中事物特征的。任何一个模型都不可能反映客观事物的一切具体特征,只能对事物特征和变化规律的一种抽象,且在它所涉及的范围内更普遍、更集中、更深刻地描述客体的特征。通过建立模型而达到的抽象是人们对客体认识的深化。
主流的编程思想
-
- 面向对象编程 (基于 类 Class)
-
- 面向过程编程 (基于 函数 函数式编程)
JavaScript 语言 并不是面向对象编程语言 在JavaScript中 没有 类(Class) 的概念 EMAScript 2015 新增的关键字 class 它并不是类 而是函数的语法糖
JavaScript的语言特性(特征) 允许用户实现 类似于 面向对象编程语言的行为(特征) JavaScript 可以被看作是面向对象语言
面向对象语言的特征
- 封装 封闭包装 将一些零散的部件放到一起 形成一个整体 -> 对象
- 继承 从其他对象中 获得东西(属性, 方法)
- 多态 多种形态(多种状态) 函数在执行过程中的多种形态
// 多态在面向对象语言中 体现形式 叫做 函数重载(允许存在 同名函数)
// JavaScript不允许函数重载
// JavaScript 不允许同名函数的出现 所以不支持这种形式的多态
// 多态的本质 根据不同的参数数量或参数类型 进行不同的操作
// function fn(arg1){
// console.log(arg1);
// }
// function fn(arg1,arg2){
// console.log(arg1+arg2);
// }
// fn(1);
// fn(1,2);
// --------------------------------------------
function fn(){
switch(arguments.length){
case 1:
console.log(arguments[0]);
break;
case 2:
console.log(arguments[0]+arguments[1]);
break;
}
}
fn(1);
fn(1,2);
Class(类)(概念)
类的概念非常抽象 它泛指一类事物 是一类事物的概括
犬类(Dog) 哺乳动物 四条腿 对主人友好 嗅觉灵敏
具体一点 哈士奇 泰迪 金毛 中华田园犬 边牧 拉布拉多 贵宾 柯基
再具体一点 具体到可以描述的个体(对象) 汪杰 养了一只金毛 1岁 母狗 名字叫 花花
类和对象的关系 将类 进行具象化 就是对象 将对象 抽象化 就是类
在面向对象编程语言中 所有的对象 都是由类创建的
在JavaScript中 对象是由函数(构造函数)创建的 在JavaScript中 构造函数 的地位 等价于面向对象编程语言中的 类
// 所有的构造函数可以看作是 类
const o = new Object();
const d = new Date();
const map = new Map();
const reg = new RegExp();
21.1 原型对象
原型对象 prototype 原型对象 是函数的一个子属性 所有的函数都拥有这个属性(箭头函数除外) 在原型对象中 拥有一个子属性 constructor 是一个指针 constructor 的指向是固定的 他指向当前原型对象 所在的函数
原型对象的作用是 存储 构造函数实例对象的 公有属性(原型属性) 如果函数被看作是普通函数使用 那么 原型对象将没有意义 只有函数被当做构造函数使用时 原型对象才有意义 他为所有构造函数创建的实例 提供 公有属性
// console.log(Phone);
// console.log(Phone.prototype);
// console.log(Phone.prototype.constructor === Phone);
Phone.prototype.abc = 123;
Phone.prototype.call = function (phoneNumber) {
console.log(`正在给${phoneNumber}打电话`);
}
const phone1 = new Phone('三星', '华为', '麒麟9000');
const phone2 = new Phone('三星', '华为', '麒麟8000');
console.log(phone1);
console.log(phone2);
// phone1.call(111111);
// phone2.call(22222222222);
console.log(phone1.call === phone2.call);
21.1.1 对象是哪里来的?
使用 new 关键字 和一个构造函数 进行创建
对象是由 函数创建 的
21.1.2 对象是如何查找属性的?
对象的属性 分为 私有属性 和 公有属性 对象查找查找属性的顺序是 优先查找私有属性 私有属性中如果没有才查找公有属性
function Foo() {
// this.f = 'abc';
}
Foo.prototype.f = 'fffff';
let o = new Foo();
console.log(o.f);
// ------------------------------------------------------------------
在JavaScript中 所有的对象 都拥有一个 __proto__ 属性
__proto__ 是一个隐藏属性 这个属性是一个指针 他指向当前对象构造函数的原型对象
console.log(o.__proto__);
console.log(Foo.prototype);
console.log(o.__proto__ === Foo.prototype);
// --------------------------------------------------------------------
let arr = [1, 2, 3];
console.log(arr.__proto__);
console.log(Array.prototype);
console.log(Array.prototype === arr.__proto__);
console.log(arr.__proto__.constructor.name);
// --------------------------------------------------------------------
console.log({}.__proto__.constructor.name);
console.log((123).__proto__.constructor.name);
console.log(/abc/.__proto__.constructor.name);
console.log('123'.__proto__.constructor.name);
console.log(true.__proto__.constructor.name);
// ---------------------------------------------------------------------
function Bar() {
this.b = 'bbbbb';
}
Bar.prototype.b = 'hello world';
let bar = new Bar();
// console.log(bar.b);
console.log(bar.toString());
console.log(bar.__proto__.__proto__ === Object.prototype);
console.log(bar.toString === Object.prototype.toString);
21.1.3 原型是什么?
原型是对象 对象是由构造函数创建的 原型对象是由创建的 -> Object 原型对象 都是Object的实例
console.log(typeof Bar.prototype);
console.log(Bar.prototype.__proto__.constructor.name);
console.log(Array.prototype.__proto__.constructor.name);
console.log(String.prototype.__proto__.constructor.name);
console.log(Date.prototype.__proto__.constructor.name);
console.log(RegExp.prototype.__proto__.constructor.name);
console.log(Map.prototype.__proto__.constructor.name);
console.log(Set.prototype.__proto__.constructor.name);
console.log(Promise.prototype.__proto__.constructor.name);
console.log(Number.prototype.__proto__.constructor.name);
21.1.4 函数的本质是什么?
函数的本质是对象 函数是由谁创建的?
console.log(Bar.__proto__.constructor.name);
console.log(Object.__proto__.constructor.name);
console.log(Array.__proto__.constructor.name);
console.log(Map.__proto__.constructor.name);
console.log(Set.__proto__.constructor.name);
console.log(Promise.__proto__.constructor.name);
console.log(RegExp.__proto__.constructor.name);
console.log(Date.__proto__.constructor.name);
console.log(Function.__proto__.constructor.name);
21.1.5 总结
- 对象 是由构造函数创建的
- 函数 是由Function创建的
- 原型对象 是由Object创建的
对象的原型对象 指向了一个空对象 所以typeof null 返回 'object' 应为null 是空对象指针 console.log(Object.prototype.__proto__);
当一个对象需要访问某个属性时 优先查找自身的私有属性 自身的私有属性如果没有 则沿 __proto__ 向上查找 在 __proto__ 如果没有找到 会继续沿 __proto__ 向上查找 __proto__ 的查找终点是 Object.prototype Object.prototype.__proto__ === null 查找到终点依旧没有发现这个属性 则返回 undefined
21.2 toString()
ECMAScript 非常多的内置构造函数 都对toStirng 进行了 重载
let arr = [1, 2, 3, 4, 5];
delete Array.prototype.toString;
在数组的原型中 就有一个toString 函数 不会向上查找 Object.prototype.toString ECMAScript 在原型上 实现了函数的重载 不同类型的数据 可以通过原型访问到不同的函数
console.log(arr.toString());
console.log(arr.toString === Object.prototype.toString);
//日期对象也重载了 toString()
let d = new Date();
delete Date.prototype.toString;
console.log(d.toString());
// 相等比较运算符
// 在比较之前有数据类型转换
// 1. 布尔值转数字
// 2. 数字和字符串对比 字符串转数字
// --------------------------------------------------------
//假设a是一个对象
//对象和字符串进行对比 对象会转字符串(调用toString进行转换)
let o = {
toString() {
return 'abc';
}
}
let str = 'abc';
console.log(o == str);
console.log(o.toString());
试题:
let a = {
values: ['animal', 'dog', 'husky'],
index: 0,
toString() {
return this.values[this.index++]
}
}
if (a == 'animal' && a == 'dog' && a == 'husky') {
console.log('哈哈 哈士奇');
}
21.3 Class
ES2015 关键字 class 创建类 ECMAScript中是没有类的 class的本质是构造函数的语法糖
在面向对象语言中 类的命名 采用 大驼峰命名法
class Student {
// 在class语法中 构造函数 使用 constructor() 表示
// 构造函数 不要添加 function 关键字
constructor(name, age, sex) {
// 构造函数中 this 表示新创建的对象
// this中的属性是 实例对象的 私有属性
this.name = name;
this.age = age;
this.sex = sex;
}
// 此处放置的是公有方法(原型方法) 也不要带 function 关键字
// class的本质 依旧是 构造函数+原型
sayName() {
console.log(this.name);
}
// 关键字 static 静态的
// 静态函数
// 静态函数和实例对象无关
// 通过类名使用
static getClassName() { // Array.from() Array.isArray() Object.create()
console.log(Student.name);
}
}
// console.log(typeof Student); // 'function'
let s1 = new Student('张三', 18, '男');
console.log(s1);
console.log(s1.__proto__);
console.log(Student.prototype);
s1.sayName();
// s1.getClassName();//报错
Student.getClassName();
21.4 Class继承
在面向对象编程语言中 类是可以实现继承的
class Father {
constructor(name) {
this.name = name;
}
getName() {
return this.name;
}
}
let f = new Father('老王');
console.log(f);
console.log(f.getName());
使用class语法实现继承 extends 关键字 用于继承父类
extends 实现继承后 可以从父类中获得公有方法(通过2次原型查找实现的)
class Son extends Father {
constructor(name, age) {
// 注意点: 使用super调用父类构造函数时 前面不允许有任何私有属性
super(name); // super函数的作用是 在子类的构造函数中 调用父类的构造函数
this.age = age;
}
getAge() {
return this.age;
}
}
let s = new Son('小王', 15);
console.log(s);
console.log(s.getName());
console.log(s.getAge());
function Father(name) {
this.name = name;
}
Father.prototype.getName = function () {
return this.name;
}
function Son(name, age) {
Father.call(this, name); // 调用父类构造函数 实现私有属性继承
this.age = age;
}
Son.prototype = Object.create(Father.prototype);
// 使用一个新对象覆盖了原有的原型对象
// 导致了 constructor 丢失
// 需要修复 constructor
Object.defineProperty(Son.prototype, 'constructor', { value: Son });
let s = new Son('lisi', 20);
console.log(s);
console.log(s.getName());
二十二、 高阶函数
其他
程序流程图
程序流程图是人们对解决问题的方法、思路或算法的一种描述。 1.流程图的优点: (a)采用简单规范的符号,画法简单; (b)结构清晰,逻辑性强; (c)便于描述,容易理解。 2.流程图采用的符号 (a)椭圆表示开始和结束 (b)箭头表示的是控制流 (c)菱形表示的是逻辑条件 (d)矩形表示的是加工步骤 (e) 平行四边形是数据
斐波那契数列(fibonacci) 黄金数列
已知数列中的前两个值是1
数列中剩余的值 是前两个值的和
1 1 2 3 5 8 13 21 34 ...
求fibbonacci 数列 第n位
fibonacci(n) = fibonacci(n - 1) + fibonacci(n - 2);
function fibonacci(n) {
if (n <= 2) {
return 1;
} else {
return fibonacci(n - 1) + fibonacci(n - 2);
}
}
console.time('fib');
console.log(fibonacci(40));
console.timeEnd('fib');
console.log(fibonacci(5));
欧几里得算法(辗转相除法)
算最大约数和最大公倍数
function gys(a, b) {
var r = a % b;
a = b;
b = r;
if (r === 0) {
return a;
} else {
return gys(a, b);
}
}
function gbs(a, b) {
return a * b / gys(a, b);
}
console.log(gys(28, 20))
console.log(gbs(28, 20))
冒泡排序法
function hubble(arr) {
var len = arr.length;
for (var i = 0; i < len - 1; i++) {
for (var j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
var temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
选择排序
function select(arr) {
var len = arr.length;
var min, temp;
for (var i = 0; i < len - 1; i++) {
min = i;
for (var j = i + 1; j < len; j++) {
if (arr[j] < arr[min]) {
min = j;
}
}
temp = arr[i];
arr[i] = arr[min];
arr[min] = temp;
}
return arr;
}
插入排序
function inser(arr) {
var len = arr.length;
var pre, now;
for (var i = 1; i < len; i++) {
pre = i - 1;
now = arr[i];
while (pre >= 0 && arr[pre] > now) {
arr[pre + 1] = arr[pre];
pre--;
}
arr[pre + 1] = now;
}
return arr;
}
桶排序
桶排序:创建桶,把数据放到桶里(对应下标的位置),遍历桶取出有数据的桶(的下标)......
function bucketSort(arr){
var bucket = []; // 1. 创建桶
for (var i = 0; i < arr.length; i++){
// 2. 把数据放到桶里(对应下标位置)
var item = arr[i];
bucket[item] = 'abc';
}
arr.length = 0; // 3. 清空数组
for (var index in bucket){
// 4. 遍历桶取出有数据的桶(的下标)
arr.push(parseInt(index));// index => string
}
return arr;
}
快速排序
快速排序:找中点,分左右,递归运算......
function quickSort(arr){
// 递归出口
if (arr.length <= 1) return arr;
// 找中点(中点的下标及值)
var midIndex = parseInt( arr.length/2 );
var mid = arr[midIndex];
// 分左右
var left = [];
var right = [];
for (var i = 0; i < arr.length; i++){
if (arr[i] === mid) {
continue; //跳过本次循环
}
if (arr[i] < mid) {//与中点比较分左右
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
// 递归运算(左中右三个数组合并)
return quickSort(left).concat([mid],quickSort(right));
}
phpstudy_pro
集成服务环境 它包含了一些web开发所需要的软件服务
7.1 开发测试环境
WAMP Windows Apache Mysql PHP (当前使用) WNMP Windows Nginx Mysql PHP
7.2 项目部署环境
LNMP Linux Nginx Mysql PHP
集成服务环境 可以更快速高效的帮助网站开发人员对软件进行测试和部署
能用于web开发的后端语言非常多 Java JSP C# ASP.NET Python PHP JavaScript NodeJS ...
不同的编程语言需要配合不同的环境和web服务器
常见的Web服务器 IIS (Windows) Tomcat (Windows Linux Unix OSX) Apache (Windows Linux Unix OSX) Nginx (Windows Linux Unix OSX)
Web服务器的配置一般不会由开发人员完成 由运维工程师完成
Web服务器的作用是为网站页面和应用提供 路由 和 数据
路由的本质 是 分支
7.3 网络传输协议
TCP/IPv4 UDP 不可靠传输协议 http:// 超文本传输协议 默认端口 80 https:// SSL加密的超文本传输协议 默认端口 443 ftp:// 文件上传下载协议 默认端口 21
IP地址 它是互联网上的唯一身份标识 每一台设备 需要上网 都需要这样一个身份标识(IP) 目前使用的 TCP/IPv4 使用的是 4组2位十六进制标识数 IP以十进制方式呈现 0.0.0.0 - 255.255.255.255
IP地址被划分成三类 A类 1.0.0.0 - 126.255.255.255 全球90%的A类地址在美国 B类 128.0.0.0 - 191.255.255.255 C类 192.0.0.0 - 223.255.255.255
7.4 域名
域名 是一种便于记忆的地址 域名可以从域名渠道商购买 目前国内的域名渠道商(万网 新网) 成功购买域名后 需要进行 公安和工信部备案
域名完成备案以后 在域名提供商的控制台 进行域名解析 所谓域名解析 是将一个备案后的域名 和一个 IP地址 进行 一一对应的映射关系(解析10分钟后同步到全网)
用户在上网时 输入地址后 第一个收到请求的 是网络服务运营商(中国电信 中国移动 中国联通) 网络服务运营商 都配备了大量的 DNS(域名解析服务器) DNS负责域名的解析工作
搜索域名表
域名 ip
www.baidu.com 180.97.34.94 www.rootbk.cn 140.143.243.131
本机地址
localhost 127.0.0.1
8 MySQL
mysql 是一个开源的关系型数据库
- 开源(免费)
- 稳定
- 安全
- 跨平台(OS) Windows Linux Unix OSX
8.1 创建数据表
### 在mysql中每一张表都应该设置一个主键(是int类型 自动增长)
CREATE TABLE `h5_2202`.`users` (
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '用户id' ,
`username` VARCHAR(255) NOT NULL COMMENT '用户名' ,
`password` VARCHAR(255) NOT NULL COMMENT '密码' ,
`email` VARCHAR(255) NOT NULL COMMENT '邮箱' ,
`phone` BIGINT(20) NOT NULL COMMENT '手机' ,
`address` VARCHAR(255) NOT NULL COMMENT '地址' ,
PRIMARY KEY (`id`)
) ENGINE = MyISAM;
8.2 插入数据
INSERT INTO `users` (`id`, `username`, `password`, `email`, `phone`, `address`)
VALUES
('100001', 'root', 'a123456', 'root@rootbk.cn', '13688888888', '浙江省杭州市上城区九堡镇旺田商务楼A座4楼');
-- 语法
insert into table (`key1`,`key2`,`key3`) values ('value1','value2','value3')
8.3 查询数据
-- 基本语法
-- * 表示所有字段
select * from table
-- 选择字段查询
select key1,key2 from table
-- 条件查询
select * from table where key=value
select * from table where key=value and key=value
select * from table where key=value or key=value
8.4 修改数据
update table set key=value where 条件
update table set key=value,key=value where 条件