目录
四、Ajax(Asynchronous JavaScript And XML)
一、PHP
1.php的安装
(1)phpstudy:集成开发环境:包含了web服务器:apache和mysql 数据库服务器
apache功能:1.实现请求和响应(必须有web服务器才能实现网络交互)
2.是php的编译环境
mysql功能:数据库服务器,对数据库进行增删查改
(2)phpstudy中最重要的文件夹www,www是服务器的部署目录
www上的文件,一定要通过地址访问
本机ip+文件名===========》本机ip等价www前的路径D:\Code\phpStudy\WWW
环形地址:和本机ip等价==========》[127.0.0.1] [localhost]
2.php语句语法
<?php
echo等价于document.write
(1) php文件除了可以处理数据外,当与echo(echo还有其他功能)连用时该php页面和html页面等价(2)php在将参数返回给ajax时,echo代表返回数据的关键字
php支持中文:header("Content-type:text/html;charset=utf-8");
注意事项:在服务路径中,再也不要出现中文了
?>
3.php的应用
(1)变量的定义
// $name = "老王";
// echo $name;
// $age = 18;
(2)php的字符串拼接用的是.
// echo $name.":".$age;
(3)if
$a = 123;
$b = 456;
$c;
if($a>$b){
$c = $a;
}else{
$c = $b;
}
echo $c;//456
(4)数组和循环
$arr = [5,4,6,7,3,8,9];
$arr = Array(5,4,6,7,3,8,9);
for($i=0;$i<count($arr); $i++){
echo $arr[$i]."<br>";
}
(5)函数
function fun($a,$b){
return $a+$b;
}
echo fun(2,3);
4.php的连接
action: 提交数据的地址
method: 提交数据的方式,默认为get
get: 五菱宏光,效率高,安全性低,携带数据量小
post: 武装押运,效率低,安全姓高,携带数据量大
name:前后端的约定,通过key来实现后端获取前端数据(input中的name属性)
(1)后端接收前端传递的数据
$_GET["key"];
$name = $_GET["userId"];
$pwd = $_GET["userPwd"];
$_POST["key"]
$name = $_POST["userId"];
$pwd = $_POST["userPwd"];
$_REQUEST["key"]:post和get都支持
$name = $_REQUEST["userId"];
$pwd = $_REQUEST["userPwd"];
echo $name .":". $pwd;(前后端接收方式必须保持一致)
(2)php连接数据库的步骤
1.登录
$conn = mysql_connect("mysql服务器地址","用户名","用户密码"):返回值为连接对象
$conn = mysql_connect("localhost","root","root");
if($conn){
echo "连接成功";
2.选择库
mysql_select_db('2202');
3.数据库的操作
mysql_query("sql语句",连接对象)**[sql语句里面的值用单引号避免冲突]
//增
// mysql_query("insert into student values (5,'小明','M','2022-4-12')",$conn);
//删
// mysql_query("delete from student where stu_name = '嘤嘤嘤'",$conn);
//改
// mysql_query("update student set stu_name='嘿嘿' where stu_id = 3",$conn);
//查:有返回值,返回值为结果集,结果集需要和其它函数结合实现特定功能
mysql_num_rows(结果集):返回结果集的记录个数 常用于判断注册登录用户是否存在?
$result = mysql_query("select * from student",$conn);
echo mysql_num_rows($result);
$result = mysql_query("select * from student where stu_name = '老王'",$conn);
if(mysql_num_rows($result) == 1){
echo "用户已存在";
}else{
echo "可以注册";
}
(2)将表中的数据提取出来:mysql_fetch_assoc(结果集):返回当前游标所指向的记录,存储在对象中
//调用完一次该函数,游标自动下移
$result = mysql_query("select * from student",$conn);
<!-- 打印出结果集所有的内容 -->
while($obj = mysql_fetch_assoc($result)){
echo $obj["stu_id"]." ".$obj["stu_name"]." ".$obj["stu_gender"]." ".$obj["stu_date"]."<br>";
}
4.关闭数据库
mysql_close($conn);
}
5.PHP返回json
xhr.open("get", "3.phpReturnJson.php?wd=2", true);
xhr.send();
前端页面将字符串转为JSON对象
let json = JSON.parse(resText);
console.log(json.name, json.age);
后端php页面有两种返回值:
a.json字符串
// echo '{"name":"老王","age":18}';
b.通过php数组返回json字符串
// $arr = ["name"=>"老张","age"=>18];
**把数组转换为json字符串:json_encode($arr)**
// echo json_encode($arr);
二、http
http(超文本传输协议)是一个基于请求与响应的应用层协议。使用TCP的80端口。
它请求遵循post和get的传参方式。
请求 B->S 响应 S->B
如何发请求?
url========>http://ip地址+端口号+文件路径
http://127.0.0.1:80/2202/Day_22/2.res.php
*ip地址*:在计算机网络中,找到服务器就需要服务器地址(类似于人的身份证号)
*端口号*:端口号代表电脑上的某个软件(的ID)
*文件路径*:文件的路径
请求的方式分为get和post
拓展:[返回响应的状态码]
1xx 接受的请求正在处理
2XX 请求正常处理完毕(成功状态码)===eg:200 响应成功
3xx 需要进行附加操作以完成请求(重定向)
4XX 客户端错误状态码===============eg:404 URL地址写错了
5XX 服务端错误状态码
拓展:[7层开放系统互连(OSI)参考模型]
物理层、数据链路层、网络层、传输层、会话层、表示层、应用层
(前3层用于数据通信,后3层用于数据处理)
三、cookie
[1]cookie(小甜饼)====》故存放数据大小为4KB左右
[2]cookie(本质)就是一个对象,用来在页面之间传递数据
1.会话跟踪技术
浏览器和服务器之间在进行多次请求数据时,数据共享的过程.
会话:一个网页打开到全部关闭的过程;
只要会话存在,cookie可以在会话阶段,在页面间传递数据并设置其生命周期。比如保存登录信息
2.cookie的使用
存/写:document.cookie = "键=值";
举例:
document.cookie = "name=laowang";
document.cookie = "pwd=123456";
注意事项:cookie必须在服务器下运行
取:console.log(document.cookie);// name=laowang; pwd=123456[由分号+空格组成的字符串]
*获取key对应的value*
let strCookie = document.cookie; //取出来
let arrCookie = strCookie.split("; "); //转为数组
console.log(arrCookie);
for (let i = 0; i < arrCookie.length; i++) {
let item = arrCookie[i].split("="); //取到=后的value
console.log(`key=${item[0]},value=${item[1]}`);
}
3.cookie传递数据
document.cookie = `name=${oInputs[0].value}`;
document.cookie = `pwd=${oInputs[1].value}`;
location.href = "6.cookie传递数据B.html";
4.cookie的生命周期
(1)会话级别
document.cookie = "name=laowang";(会话在cookie在,会话没cookie没)
(2)长生命周期
通过设置时间,打破了会话级别的生命周期
document.cookie = "key=value;expires="+标准日期对象;
// let date = new Date();
// date.setDate(date.getDate() + day);
// document.cookie = "name=laowang;expires=" + date;[七天免登录原理]
5.删除cookie
cookie的删除强调的是长生命周期
cookie的删除没有直接删除的方式,只能侧面删除(a、b必须一起使用)
// a.将key对应的value设置为''
// b.将expires设置为-1
document.cookie = "name='';expires=-1";
6、封装Cookie
function getCookie(key) {
let strCookie = document.cookie;
let arrCookie = strCookie.split("; ");
for (let i = 0; i < arrCookie.length; i++) {
let item = arrCookie[i].split("=");
if (item[0] == key) {
return item[1];
}
}
return "";
}
//增改
//注意事项:会话级别
// 长生命周期
function setCookie(key, value, day) {
//会话级别
if (day == undefined) {
document.cookie = `${key}=${value}`;
} else {
let date = new Date();
date.setDate(date.getDate() + day);
document.cookie = `${key}=${value};expires=${date}`;
}
}
//删
function delCookie(key) {
setCookie(key, '', -1);
}
四、Ajax(Asynchronous JavaScript And XML)
前提:在发送请求的操作中,页面必然要重新刷新
问题:很多页面在发请求的过程中,只有少量数据需要更新,
如果完全刷新页面重新渲染,会给用户造成不好的体验。
解决该问题的方案:
1.概念
异步交互的javascript和xml,是一种可以实现页面在发请求时,无需更新整个页面,只需对局部内容更新的技术;[局部刷新页面]
前端通过与服务器进行少量数据交换,AJAX可以使网页实现异步更新,这意味着在不重新加载整个网页的情况下,对网页的某部分进行更新;传统的网页(不使用Ajax)如果需要更新内容,必须重载整个网页页面。
2.为什么要使用AJAX?(好处)
// * 更自然、流畅的用户体验,对用户的操作[即时响应]
// * 在[不中断用户操作]的情况下与Web服务器进行通信
// * 更灵敏的[响应用户访问],实现近似于桌面应用程序的交互效果
// * 通过局部更新页面[降低网络流量],提高网络的使用效率
3.Ajax的优缺点
优点:1)可以无需刷新页面而与服务器端进行通信;
2)允许你根据用户事件来更新部分页面内容。
缺点:1)没有浏览历史,不能回退;
2)存在跨域问题(同源);
3)SEO[搜索引擎优化]不友好。
拓展:SEO的作用:获取流量,提高网站排名
4.同步和异步
同步执行方式:代码按顺序执行,先执行完前一步,才能执行后一步,若遇到消耗时间的代码,则变阻塞状态。
异步执行方式:代码在遇到消耗等待时间的代码时,会先跳过异步代码,先执行后续代码,再执行异步代码。
*哪些代码需要消耗等待时间?*
1.事件体
document.onclick = function(){ 事件体 }
2.定时器的回调函数
3.发请求和接响应
*总结*:
当同步代码和异步代码同时出现时,同步代码优先执行,异步代码后执行;
只有同步代码遵循自上而下的执行顺序;异步代码的执行顺序和书写顺序没有关系;
5.Ajax的编写步骤
1.创建一个XMLHttpRequest对象
let xhr = new XMLHttpRequest();
2.调用open方法,传递服务器地址及参数,true为异步,false为同步
xhr.open(请求方式,服务器地址,是否异步);
3.发射
xhr.send();
4.等待对方接电话(这一步开始消耗等待时间)
xhr.onreadystatechange = function() {
if (xhr.status == 200 && xhr.readyState == 4) {
5.对方回复你信息
//**xhr.responseText**
fun(xhr.responseText);
}
}
6.调用function fun(resText) {
console.log(resText);
}
6.属性分析
[1]XMLHttpRequest:ajax操作时的核心类型
该类型生成的对象拥有发送请求和接收响应的所有属性和方法
[2]如果传参方式为get,则url地址后拼接参数open()
get传参:url?key1=value&key2=value2...
[3]发送请求:xhr.send([参数])
get传参: send中什么都不写
post传参:xhr.send(key1=value1&key2=value2...)
[4]readystate属性发生改变时触发的事件
readyState:xhr对象的状态码,不同时刻状态码不同
status:http协议正常通讯的状态码
readyState状态码发生改变时触发该事件,只有2、3、4状态会触发该事件
// 0:代表xhr对象创建
// 1:调用了open方法
// 2:调用了send方法,发送了出去
// 3:数据发送到了服务器
// 4:服务器接收数据且处理完毕,准备响应
7.Ajax传参方式
(1)get传参方式
ip:端口+文件名?key1=value1&key2=value2....
**xhr.open("get", "2.AjaxGet.php?userName=" + this.value, true);**
**xhr.send();**
(2)Post传参方式:
**xhr.open("post", "2.ajaxPost.php", true);**
1.open方法后和send方法间一定要设置请求头
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
2.将键值对写在send中
**xhr.send("userName=" + this.value);**
8.封装ajax
封装ajax的目的就是发送请求参数,获取返回的响应内容
功能:发请求,接响应
参数:
// type:请求方式
// url:文件路径
// isAsyn:是否异步
// data:key1=value1&key2=value2
// callBack:回调函数
function ajaxFun(type, url, isAsyn, data, callBack) {
let xhr = new XMLHttpRequest();
type = type.toLowerCase();
if (type == "get") {
let urlParam = url;
if (data != "") {
// url?data
urlParam += "?" + data;
}
xhr.open(type, urlParam, isAsyn);
xhr.send();
} else if (type == "post") {
xhr.open(type, url, isAsyn);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.send(data);
} else {
console.log("传参方式错误");
return;
}
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
callBack(xhr.responseText);
}
}
}
五、 Promise(ES6规范)
是一个对象,该对象是处理异步操作的一种方法.类似一个容器,可存放异步操作.(发请求接响应)
作用:可以将回调函数嵌套的写法,改为平级调用
1)从语法上来说: Promise是一个构造函数
2)从功能上来说: promise对象用来封装一个异步操作并可以获取其成功/失败的结果值
1.概念详解
它是一种异步操作的解决方案,将写法复杂的传统回调函数和监听事件的异步操作,
用同步代码的形式表达出来.避免了多级异步操作的回调函数嵌套.
(1)主要用于异步计算
(2)可以将异步操作队列化,按照期望的顺序执行,返回符合预期的结果
(3)可以在对象之间传递和操作promise,帮助我们处理队列[先进先出]
2. promise语法
var promise = new Promise(function(resolve, reject) {
// ... some code
if ( /* 异步操作成功 */ ) {
resolve(value);
} else {
reject(error);
}
});
3.为什么要使用它?
[1]指定回调函数的方式更加灵活;
promise:启动异步任务=>返回promise对象=>给promise对象绑定回调函数.
[2]支持链式调用,可以解决回调地狱问题;
4.Promise的3种状态
1)初始状态(pending);
2)已完成(resolve): resolve方法可以使Promise对象的状态改变为成功;
3)已拒绝(reject): reject方法则是将Promise对象的状态改变为失败;
Promise构造函数有两个变量,配合then与catch一起使用:
resolve:用于返回异步执行成功的函数;
reject:用于返回异步执行失败的函数;
5. Promise常用的3种方法
第一种: *then*表示异步成功执行后的数据状态变为resolve;
第二种: *catch*表示异步失败后执行的数据状态变为reject;
第三种: *all*表示把多个没有关系的Promise封装成一个Promise对象使用then返回一个数组数据。
6.all和race
Promise.all场景:一个页面需要同时发送多个请求,等待所有请求结束时,统一接收响应.[一起获取]
Promise.race场景:获取同样的数据,有N个服务器,可以一次发多个请求,谁快获得谁的响应.
六、跨域
1.概念
网站A的页面访问网站B服务器的某个文件,跨域名访问
2.同源策略
浏览器只能访问,同IP,同端口,同协议的文件
浏览器的安全机制同源策略,避免知道IP和文件名就能访问你文件内容
实际工作中,是需要频繁跨域的
//如访问地图信息,天气信息,搜引擎信息...
3.前端跨域的方式:jsonp
//在前端中,src属性是可以跨域的
//jsonp:不是语法,是一种跨域的技巧,本质是依赖于src属性实现
jsonp实现步骤
//1.前端后端约定一个函数名
//2.前端写函数定义
//3.后端写函数调用
//4.前端通过srcipt的src访问后端文件
//5.后端在文件中,模拟函数调用将响应内容传递给前端
注意:
1、jsonp没有使用XMLHttpRequest对象。
2、jsonp只是一种跨域的技巧。
3、jsonp只支持Get方式
由于按照jsonp的这种方式跨域访问时,好像可以利用javascript和服务器端交互,
能达到AJAX中XMLHttpRequest对象同样的效果。所以,人们总是把jsonp和AJAX联系在一起。
4.后端跨域:cors[跨域资源共享]
面试题:jsonp和json的区别?
1、jsonp和json根本就没有关系
2、jsonp是跨域访问的技巧
3、json是描述数据格式
5.接口
接口:后端给前端提供的服务器文件,前端根据不同的接口发出不同的请求,获取对应的响应。
**接口的四要素**
*type*:get/post
*url*:服务器地址
*data*:请求参数
*resText*:响应数据
前提: 匿名函数
函数的本质就是一个变量
变量--->对象
所以函数是一个对象:凡是可以使用对象的地方,都可以使用函数
特殊的两个使用方式:
1.函数对象作为参数:回调函数
2.函数对象作为return的返回值(闭包的学习基础)
七、自运行
自运行针对于,匿名函数
概念:一个函数在定义时,同时被调用,称为自运行
为什么需要自运行,只是闭包写法的先前条件
1.自运行的3种表现形式
a.用()括起来所有代码(常用这种方法)
b.用()括起来匿名函数对象
c.依赖于运算符(!)和关键字(void)
八、闭包
1.概念
函数嵌套函数,被嵌套的函数称为闭包函数
2.作用
可以在函数外部使用函数的局部变量
3.闭包实现的步骤
[1]主函数定义局部变量,嵌套定义子函数;
[2]子函数中使用父函数的局部变量,主函数将子函数作为返回值;
[3]在外部通过一个全局变量,绑定主函数的返回值(子函数对象);
[4]从而将子函数和子函数中使用的局部变量变为全局生命周期,这样就可以在主函数外界使用局部变量.
4.缺陷
打破了垃圾回收机制,延长了局部变量的生命周期,可能会造成内存泄露
function f1(){ //闭包写法展示
var count = 0;
var f2 = function(){
++count;
return count;
}
return f2;
}
(1)垃圾回收(GC)
就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾,这些垃圾积攒过多以后,会导致程序运行的速度过慢,所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾.
当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢.所以这种垃圾必须进行清理。
在JS中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,我们不需要也不能进行垃圾回收操作,我们需要做的只是要将不再使用的对象设置nul1即可.
(2)内存溢出和内存泄漏
1.内存溢出
*一种程序运行出现的错误
*当程序运行需要的内存超过了剎余的内存时,就出抛出内存溢出的错误
2.内存泄露
*占用的内存没有及时释放
*内存泄露积累多了就容易导致内存溢出
常见的内存泄露:
*意外的全局变量
*没有及时清理的计时器或回调函数
*闭包
5、函数对象的定义(3种)
//a.
function fun(){
console.log("heihei");
}
//b.
let fun1 = function(){
console.log("haha");
}
//c.
// let fun2 = new Function([参数列表],函数体);
// let fun2 = new Function("a","b","console.log(a+b)");
九、函数体内的内置对象
1、this
1.**与事件连用,代表触发事件的元素**
document.onclick = function(){
console.log(this); //输出:document
}
2.**与普通函数连用(除了事件体,和构造函数),代表调用该函数的对象**
function fun(){
console.log(this); //输出:window
}
window.fun();
-----------------------------------------------------------------
let json = {
a:1,
fun:function(){
console.log(this); //输出:{a: 1, fun: ƒ}
}
}
json.fun();
3.***与箭头函数连用,代表父元素前缀**
let json = {
a:1,
fun:()=>{
console.log(this); //输出:window
}
}
json.fun();
4.**与构造方法连用,代表new出来的对象本身**
function Student(id){
this.id = id;
}
2、arguments
保存着所有实参的伪数组,它只能读取元素,不能调用数组相关的API。
作用:*可以定义不定参函数*
arguments.callee:代表该函数对象本身
在递归中可以使用callee属性代表函数对象本身,避免了外部改函数名,内部也需要改的问题
递归:一个函数直接或者间接的调用自己本身;作用:可以将代码变短
例题举例:有5个小孩依次排列,问第五个小孩多大?他比第四个小孩大2岁,以此类推,第一个小孩说他10岁。
递归函数: function asd(n) {
let c;
if (n == 1) {
c = 10;
} else {
c = arguments.callee(n - 1) + 2;
}
return c;
}
console.log(asd(5)); //输出:18
十、函数对象的属性portotype(原型对象)
场景:行为方法属于整个类族,而不是某一个对象,所以我们需要一块空间,存储所有类族的方法
属性都是唯一独立的,方法不是属于某一个对象,是属于整个类族的;
如果每个实例化对象创建时,都要重新创建study函数对象,会浪费内存空间;
解决方案:**原型对象prototype**
每一个函数对象(只强调作为类的函数)都有一个属性prototype,它称为原型对象;
*拓展:*
如果函数作为普通函数调用prototype没有任何作用
当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,我们可以通过__proto__来访问该属性;
prototype就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容统一设置到原型对象中。
当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用;
以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了.
函数对象.prototype作用:
存储所有实例对象共享的方法和属性
1.为什么实例化对象能访问所有的属性和方法?
==========>原型图
答:(1)实例对象创建时,会[开辟属性空间],所有可以直接访问;
(2)其次每个实例对象构造的同时,还会[创建一个_proto_属性],该属性指向类的原型对象,所以实例对象便可以访问原型对象上的属性和方法
注意:
(1)实例对象不可以改变prototype上的属性和方法
(2)如果实例化对象改变了原型属性,则等价于为自己添加了个同名属性,覆盖了原型属性
十一、apply和call
apply和call是函数对象的方法,他们的作用是*改变函数的this指向*
**函数对象.call(this指向,函数对象真实的参数1,参数2...);**
**函数对象.apply(this指向,[函数对象真实的参数1,参数2...]);**
好处:可以将函数和类进行解耦=============>[耦合性]指程序每个模块间的关联性强弱
解耦:就是解除耦合关系
**耦合**是指2个/2个以上的体系/2种运动形式间,通过相互作用而彼此影响以至联合起来的现象
1、面试题:apply,call,bind的异同?
1.都是用来改变函数this指向的; [同]
2.bind主要针对于匿名函数,apply和call针对于有名函数;
3.apply和call的第2个参数不同: apply需要把参数写在一个数组中,call不需要;
4.apply和call会直接调用原来的函数对象,
bind并不是直接调用原函数,等价创造了一个新的函数对象,还需要重新调用.
十二、继承(子类继承父类)
继承:父类可以派生出子类,子类具备父类的属性和方法,子类还可添加自己新的属性和方法
作用:继承可以大大提高代码的复用性,子类可以添加新的属性和方法,创建新的类
1、原型链继承(ES5)
含义::通过原型对象实现继承
让子对象的原型指向父对象的实例,父对象的原型指向爷爷对象的实例,依次类推,就形成了原型链.
#### 原型继承:用子类的原型对象指向父类的实例化对象
代码翻译:
子类.prototype = new 父类构造函数();
作用:
*子类实例化对象可以直接使用父类创造的属性和方法,并且子类可以添加新的属性和方法*
缺陷:
(1)*无法在子类对象构造时,初始化父类派生给子类的属性*
(2)*必须先实现继承关系,再为子类添加新的方法,否则会覆盖*,继承关系实现后,不可以重写prototype
子类对象是如何访问所有属性和方法的?=========》原型图:必须画出来
2、原型图
//子类对象可以直接自身new出的属性,通过_proto_可以访问该类原型对象上的属性和方法,
//该类原型对象指向其父类的实例化对象,所以可以访问父类的属性
//父类的实力对象的_proto_也指向自身类的prototype,所以可以访问父类原型对象的属性和方法
*原型链:*
//多个类纵向继承,在访问任意属性时,先在自身查找该属性,找不到取原型找,
//在找不到就去找父级元素,依次向上找,祖宗类都找不到,就报错
3、判断一个引用类型对象是什么类型?
*引用对象 instanceof 类型: 返回布尔值*
面试题:typeof和instanceof的异同?
1.他们都是用来判断数据类型的[同]
2.typeof只能用来判断基本类型:如number,string,boolean(判断引用类型只是一个模糊的“object”)
3.installceof是用来判断引用类型的(可以弥补typeof无法细分引用类型的缺点)
4、apply和call的继承
通过借用构造方法实现"继承"
问题:原型继承是无法在子类对象构造时,初始化父类派生给子类的属性
通过apply和call"继承":可以解决子类对象构造父类属性的问题(解决原型继承的'缺陷1')
缺陷:子类对象无法访问原型对象上的属性和方法
5、混合继承
ES5实现继承使用混合继承,即原型对象和apply,call同时使用
属性:apply,call
原型属性:原型对象实现
6、 ES6继承
class 子类 extends 父类 {
constructor() {
super(参数);//借用父类的构造方法,继承父类的属性
}
}
注意:*super就是父类的constructor(构造方法),super必须写在第一行*
ES6是语法糖衣, 本身并没有改变js继承的机制, 只是看起来方便些
十三、深浅拷贝(克隆)
拷贝:由已有对象去初始化一个新的对象
深浅拷贝只针对于引用类型,与内置基本类型无关
内置类型和引用类型在内存中存储的区别:
内置基本类型:只有一块栈空间,存储的是数据本身
引用类型:有两块空间,一块栈空间,一块堆空间
栈存储的是堆空间的地址 堆存储的是真正的数据
**浅拷贝**:只赋值但并未开辟空间,两个元素用的是同一地址,通过任意对象都可以修改堆空间的内容,其中一个改变了数值,另一个也会被修改。
**深拷贝**: 每个引用对象都必须得new空间,开辟空间且赋值,两个对象都有独立的空间,被拷贝的对象只是和原对象数值相同
十四、本地存储
localStorage 等价于长生命周期的cookie
sessionStorage 等价于会话级别的cookie
// *getItem(key)*:获取指定key所存储的value值
// *key(index)*方法:返回列表中对应索引的key值
// *length*属性:返回key/value队列的长度
// *removeItem(key)*方法:从Storage中删除一个对应的键值对。
// *setItem(key,value)*方法:将value存储到key指定的字段。
// *clear()*方法:移除所有的内容
**增改**(3种方式)
a.setItem("key","value");
b.点运算符
c.下标法
**查**(3种方式)
a.getItem("key"):返回value
b.点运算符
c.下标法
**删**
localStorage.removeItem("name");[局部删除]
localStorage.clear();[整体删除]
**存储json**
localStorage.setItem("data", '{"name":"老王","age":"18"}');[存]
let str = localStorage.getItem("data");[取]
console.log(str); //{"name":"老王","age":"18"}
let json = JSON.parse(str);
console.log(json.name, json.age); //老王 18
**遍历**
// 键值对个数
for (let i = 0; i < localStorage.length; i++) {
// *localStorage.key(下标):返回下标对应的key*
console.log(localStorage.key(i)); //data
// ket=>value就可以获取了
}
面试题:cookie、localStorage、sessionStorage的异同?
[1]数据的生命周期:
一般由服务器生成,可设置失效日期,浏览器端生成的C在关闭浏览器后就失效;
L除非被清除,否则永久保存; S仅在当前会话下有效,关闭页面后就被清除;
[2]存放数据大小:
C大小在4K左右;L和S一般为5MB;
[3]与服务器端通信:
C每次都会携带在HTTP头中,用它保存过多数据会带来性能问题;
L和S仅在客户端(浏览器)保存,不参与通信;
[4]易用性:
C需程序员封装,源生的接口不友好;L和S源生接口可以接受,也可再次封装对Object和Array有更好的支持;
十五、设计模式(类的设计方案)
1、定义
模式是在一个上下文中,对一个问题的解决方案。
即*模式的四要素*:名字、上下文、问题和解决方案。
设计者: 使用者:
1.设计功能模块 1.引入插件
2.提供使用手册(api) 2.按照设计文档使用插件
3.提供插口(HTML,CSS)
举例:单例模式、观察者模式、代理模式、工厂模式、抽象工厂模式、适配器模式等
2、设计模式---观察者设计模式
两个角度
a.观察者,订阅者
b.发布者,主题
核心思想:
订阅了主题的观察者,可收到主题发送的消息
在订阅者中写函数定义,观察者中写函数调用,传递参数(消息)给订阅者
弹出框案例
注意:凡是和offset有关的属性,元素必须先在页面显示,才能使用(先挂载/显示,offset才有数值)
选择器案例
静态方法:被static修饰的方法,静态方法通过类名调用