函数的四种调用模式

1、普通函数执行

  • this -> window
  • 声明一个函数后,就直接调用
    code block
    1
    2
    3
    4
    5
    function foo() {
    console.log(1);
    console.log(this === window);//true
    }
    foo();

2. 方法调用模式

  • this —> 该方法的调用者
  • 通过一个对象来调用方法

    1
    2
    3
    4
    5
    6
    7
    var obj = {
    sayHi: function() {
    console.log("hello, girl.");
    console.log(this === obj);//true
    }
    };
    obj.sayHi();

3. 构造函数模式

  • this -> 当前创建出来的对象
  • 配合new操作符 来 调用函数

    1
    2
    3
    4
    5
    6
    7
    function fn(name, age, gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    console.log(this);
    }
    var f = new fn('f');

4. call/apply(上下文)模式

  • this -> 用户动态指定的
    • 指定call or apply 方法的第一个参数
  • 区别:
    • .call(thisObj, arg1, arg2, …,argN):thisObj为 this的指向。之后为形参列表,就是fn在执行时的实参列表
    • .apply(thisObj, [实参]): thisObj 为 this的指向,数组参数为 fn在执行时的实参
  • 注意:在非严格模式下,如果thisObj 赋值为 null 或者不传实参,此时this -> window 对象,就相当于 普通函数执行模式。

    1
    2
    3
    4
    var o = {};
    fn.call(o, 'o', 18, 'man');
    fn.apply( o, ['o', 18, 'man'] );
    console.log(o);

5. 上下文模式的应用

+ 1 数组的合并
1
2
3
4
var arr1 = [1, 2, 3];
var arr2 = [4, 5 ,6];
Array.prototype.push.apply(arr1, arr2);
console.log(arr1);
+ 2 借调方法(函数)
- 借用原生方法
      + 求数组中的最大值
      + 获取内置对象类型
      + 将伪数组变成真数组
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// a:借用构造函数
function parent(name,age,gender){
this.name=name;
this.age=age;
this.gender=gender;
}
function child(name, age, gender, address) {
parent.call(this, name, age, gender);
this.address = address;
}
var c = new child('c', 19, 'nicai', 'yueqiu');
console.log(c);
// b: 借调原生方法
var data = [67, 89, 190, 23, 10, 100];
// 求data中的最大值
var max = Math.max.apply(null, data);
console.log(max); // 100
// c: 获取内置对象类型
console.log(typeof 1);
console.log(typeof []); // "array"
console.log(typeof new Date); //"date"
// 功能:如果是内置对象,返回其类型名;eg. [] -> "array", 1 -> "number"
// 如果是自定义对象,就返回"object".
function getType(obj) {
// return Object.prototype.toString.call(obj).slice(8, -1).toLowerCase();
// var patt = /^\[\w+ (\w+)\]$/;
var patt = /^\[object (\w+)\]$/;
var str = Object.prototype.toString.call(obj);
var match = patt.exec(str);
return match[1].toLowerCase();
}
console.log(getType(/a/));
- 借用原生方法
  + 求数组中的最大值
  + 获取内置对象类型
  + 将伪数组变成真数组

6. 数组去重

  • 实现思路:
    • 声明一个函数实现数组去重,取名为unique;
    • 判断浏览器是否支持数组的indexOf方法
    • 如果不支持,就自己实现数组的indexOf方法,并且将其扩展到数组的原型对象上。
    • 遍历数组,首先判断结果数组ret中是否含有当前遍历到的元素,
    • 如果没有,就将当前元素添加到ret中。
    • 循环结束,将ret返回。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
var arr = [1, 2, 2 , '1'];
// indexOf
function unique(a) {
var ret = [];
// 如果不支持indexOf方法
// 自己实现数组的indexOf方法,并添加到数组的原型对象上。
if( !ret.indexOf ){
Array.prototype.indexOf = function(val) {
// this指向的就是 indexOf的调用者 (数组对象)
// 如果循环顺利执行完,就表示没有val值,返回-1;
// 否则返回val在当前数组中的下标值。
for(var i = 0,l = this.length; i < l; i++){
if(this[i] === val) return i;
}
return -1;
};
}
for(var i = 0,l = a.length;i < l; i++){
// 如果ret中不存在当前遍历到的元素,就添加到ret中
// 否则就不要添加
if( ret.indexOf(a[i]) === -1 ){
ret.push(a[i]);
}
}
return ret;
}
console.log(unique(arr));

1. instanceof运算规则:

如果运算符后面的函数 的prototype属性所引用的对象,
出现在 运算符前面的对象 的原型链上的话,就返回true;
否则就返回false,(只要是在原型链上就输出true)。
code block:

1
2
3
4
5
var f = new foo;
console.log(f instanceof foo);// true
console.log(f instanceof fn); // false
console.log(f instanceof Object); // true
// f -> foo.prototype -> Obejct.prototpye - > null

2. 绘制作用域链的规则

  1. 将整个script标签的全局作用域,定义为0级作用域链。将全局作用域上的数据(变量、函数、对象等等)绘制在该链上。
  2. 由于在词法作用域中,只有函数可以分割作用域。因此,只要遇到函数,就要引申出新的作用域链,级别为当前链的级别 + 1;
  3. 重复第二步骤,直到没有遇到函数为止。

3. 变量的搜索原则:当访问一个变量时,

  1. 首先在当前变量所处作用域链上查找,如果找到就直接使用,并停止查找;
  2. 如果没有找到,就向上一级链(T - 1)上去查找,如果找到就直接使用,并停止查找;
  3. 如果没有找到,就继续向上一级链查找。直到0级链,如果找到就直接使用,并停止查找;
  4. 如果没有找到就报错。

注意:

  • 如果访问的变量不存在,会搜索整个作用域链(不仅性能低,而且抛出异常。)
    在实际开发,不推崇所有数据都写在全局上。尽量使用局部变量。推荐使用沙箱。
    如果在开发中,所有js代码都写在全局上,会造成全局变量的污染。
    
  • 同级别的链上的变量互不干扰。

4. 在函数执行的时候,会创建一个执行的环境,包括activeObject(活动对象)以及作用域链

1> activeObject: 存储的是所有在函数内部定义的变量,以及函数的形参;
会将变量名字以及形参名字作为该对象的属性来存储

5. 闭包

  • 概念:一个函数有权去访问另一个函数的内部数据。(就是要访问函数中的变量,在函数的里头建立一个函数,利用这个函数来输出这个变量然后在放回这个函数,这样就实现了)
  • 缺点: 会造成函数内部的数据常驻内存,从而引发内存泄漏的问题。
  • 解决的问题:解决在函数外部无法访问函数内部的数据。
  • 为了防止闭包导致内存泄漏,在使用完闭包后,将其赋值为null即可。
  • 闭包怎么缓存数据?因为在函数内部有方法(函数)对其有引用,并且又将其返回到外部作用域上的一个变量接收。

6. 垃圾回收机制:GC(Garbage Collection)

  1.  引用计数

    如果一个变量被另一个变量引用,那么该变量的应用计数+1;当这个变量不再引用该变量(该变量被回收掉了)时,
    此时这个变量的引用计数 - 1;
    GC会在一定时间间隔去查看每个变量的计数,如果为0, 就将其占用的内存回收。
    

    缺点: 循环引用:会造成无法回收变量的内存

    a{ val : b} , b{val:a} b = null;(a = null)
    

2. 标记清除

从当前文档根部(window对象)找一条路径,如果能到达该变量,那么说明此变量不应该 被回收掉
反之,应该被回收其所占用的内存。
- --如果变量进入某个执行环境,那么给其标记为 “进入环境”;
- --如果上述执行环境执行完成,被销毁,那么该环境内的所有变量都被标记为“已出环境”
- --如果变量被标记为已出环境,就会被回收掉其占用的内存空间。

7. 闭包的应用

  1. 计数器
  2. 对象的私有属性
  3. 解决fib数列递归性能
  4. 沙箱模式: 好处: 不会污染全局变量(或者其他作用域的变量),并且能保证自己的代码安全执行。

    特性: a: 能分割作用域,不会污染全局 fn

    b:  在分割后的作用域内部的代码要能自执行。fn()
    

    结构:
    (function (){

    //代码块
    window.fn = fn;        
    

    }());

各种请求和响应

a标签

a标签 的数据一般是用GET方式的请求,,然后在herf中填入的是请求的地址,最后用get方式来发送数据

block
1
<a href="01demo.php?username=zhangsan&age=12">get 方式提交</a>

form类的

form 的发送,一般使用这个post
然后在这个里头增加input的标签在input中的name=”username” 就是这个变量的名字。
用户写入input的内容就是username的内容。

在php中获取。
$username = $_GET[“username”];
$username = $_POST[“username”];
echo $username ;
这样点击提交跳转到php的这个页面输出username 的值

注意

  • 一定会有一个input标签type的值为submit用来提交
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
我要把这个临时的文件放在我的自己的目录下面.
我可以调用php给我提供的另外一个函数.
<form action="01demo.php" method="post" enctype="multipart/form-data">
<input type="file" name="lifephoto"/> <br />
<input type="submit" value="文件上传"/>
</form>
(记住这个图片的名字必须是中文的不然就出错了)
/*
1:我要移动的文件的目录.
C:\wamp\tmp\php6C62.tmp
2:我要移动到那个文件夹里面的那个文件里面去
images/2.txt
*/
//获取文件临时存储位置.
$tmp_name=$_FILES['lifephoto']['tmp_name'];
//获取文件名称 images/1.png
$fileName=$_FILES['lifephoto']['name'];
//把文件移动到另外的一个指定的目录的文件当中
move_uploaded_file($tmp_name,"images/".$fileName);
*变量要一一对应*

php 的动态输出

简单的来说这就是一个html页面中间要把自己的php部分用php语言的格式然后利用echo,在这个页面输出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>订单页面</title>
</head>
<body>
<table>
<tr>
<td>姓名</td>
<td>性别</td>
<td>描述</td>
</tr>
<?php
//我在这里从数据库里面取出来数据
//取出来的数据肯定放在一个临时的存储区。
//从数据库里面的数据取出来放在一个数据当中,
//我把这个数据里面的数据遍历出来,再进行输出.
$array=array(
array("name"=>"chen","sex"=>"男","detail"=>"有点帅"),
array("name"=>"li","sex"=>"女","detail"=>"很帅"),
array("name"=>"wang","sex"=>"男","detail"=>"超帅"),
);
for($i=0;$i<count($array);$i++){
echo "<tr>";
foreach($array[$i] as $key=>$val){
echo "<td>";
echo $val;
echo "</td>";
}
echo "</tr>";
}
?>
</table>
</body>
</html>

说明:

中间的那一部分就是php的内容就可以向页面输出信息

xml格式,json格式数据(都是ajax请求ajax单独讲)

什么是xml格式的数据? 类似标签

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
<?xml version="1.0" encoding="utf-8"?>
<users>
<user>
<username>张三</username>
<sex></sex>
<desc>美女</desc>
<imageURL>images/1.jpg</imageURL>
</user>
<user>
<username>李四</username>
<sex></sex>
<desc>有韵味</desc>
<imageURL>images/2.jpg</imageURL>
</user>
<user>
<username>王五</username>
<sex></sex>
<desc>大美女</desc>
<imageURL>images/3.jpg</imageURL>
</user>
<user>
<username>xxx</username>
<sex></sex>
<desc>大美女</desc>
<imageURL>images/3.jpg</imageURL>
</user>
</users>

后缀名字为xml
什么是json格式的数据 key:value键值对
文本的后缀是txt

1
2
3
4
5
6
{"rows":[
{"username":"冰","age":21,"sex":"女","desc":"云南来的汉族妹子"},
{"username":"石健","age":23,"sex":"男","desc":"帅哥一枚"},
{"username":"王春淼","age":22,"sex":"女","desc":"命里缺水"},
{"username":"齐飞龙","age":22,"sex":"男","desc":"就是一条龙"}
],"total":20}

服务端对xml,json的解析然后给客户端

  1. 对xml解析:

    1
    2
    3
    header("Content-Type:text/xml;charst=utf-8");
    $data=file_get_contents("02demo.xml");
    echo $data;
  2. 对json的解析:

1
2
3
header("Content-Type:text/html;charset=utf-8");
$data=file_get_contents("01json.txt");
echo $data;

客户端对这种格式数据的处理

1.对上面的xml格式的处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
var data=xhr.responseXML;(关键方法,下面要知道怎么用获取到的数据)
//我要把这些数据解析,通过dom 解析
//解析组装成标签,放在我页面对应的位置.
var users=data.getElementsByTagName("user");
for(var i=0;i<users.length;i++){
var tr=document.createElement("tr");
//创建四个td
var td1=document.createElement("td");
var td2=document.createElement("td");
var td3=document.createElement("td");
var td4=document.createElement("td");
//给每个td 给赋值。
td1.innerHTML=users[i].getElementsByTagName("username")[0].innerHTML;
td2.innerHTML=users[i].getElementsByTagName("sex")[0].innerHTML;
td3.innerHTML=users[i].getElementsByTagName("desc")[0].innerHTML;
//找个里面目前放置的是一个图片的地址.
var img=document.createElement("img");
img.setAttribute("src",users[i].getElementsByTagName("im ageURL")[0].innerHTML);
td4.appendChild(img);
tr.appendChild(td1);
tr.appendChild(td2);
tr.appendChild(td3); tr.appendChild(td4);
document.querySelector("table").appendChild(tr);
}

  1. 对于json的处理(注意获取和使用的方法)

JSON.parse()、JSON.stringify()括号中就是数据,,这个函数会将数据转化为JSON格式的
JSON兼容处理json2.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
//调用这句出问题. 符合json 格式的字符串,才能被转换
var data1=JSON.parse(data);
//alert(data1);
alert(data1.username);
alert(data1.age);
//第二种转换方式
js 给我们提供了一个方法 这个方法叫做
eval() //把json 格式字符串传进去
{"username":"zhangsan","age":11}
eval 函数有要求,要求传进去的json 格式字符串必须使用()
//({"username":"zhangsan","age":11})
var obj=eval("("+data+")");
alert(obj.username);
alert(obj.age);

客户端利用模板引擎来对数据进行解析(是对json格式的数据)

以上面的json格式的数据为例子

  1. 肯定需要导入js/template-native.js
  2. 创建一个模板(不知道模板怎么去创建,,模板里面的内容怎么去写.)

网络传输协议

指服务器和客户端间进行通信时的约束和规范,客户端与服务端的数据交互并不是杂乱无章的,需要遵照(基于)一定的规范进行。

常见的协议

  • HTTP、HTTPS 超文本传输协议
  • FTP 文件传输协议
  • SMTP 简单邮件传输协议

HTTP协议

即超文本传输协议,网站是基于HTTP协议的,例如网站的图片、CSS、JS等都是基于HTTP协议进行传输的。
HTTP协议是由从客户机到服务器的 请求(Request)和从服务器到客户机的 响应(Response)进行了约束和规范。
即HTTP协议主要由请求和响应构成。

1.请求/请求报文

code block:
请求首行:GET /day08/code/01PHP/01demo.html HTTP/1.1
请求头(知道请求空行都是): Host: 127.0.0.1
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36(浏览器内核等)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,/;q=0.8 //接收
Referer: http://127.0.0.1/day08/code/01PHP///当前的请求来自于那个页面.
1:用来做广告流量统计
2:防盗链
Accept-Encoding: gzip, deflate, sdch//告诉服务器我这边接收的一个数据压缩格式.
Accept-Language: zh-CN,zh;q=0.8 //接受的语言格式.
请求空行 (这边有一行空的)
请求体:就是数据(get没有请求体只有post有)

2.响应/响应报文

结构跟上面的是一样的。
这个是响应头:
Date: Wed, 21 Sep 2016 02:34:52 GMT//告诉客户端浏览器我服务器的版本
Server: Apache/2.2.21 (Win32) PHP/5.3.10
Last-Modified: Wed, 21 Sep 2016 01:28:05 GMT // 最后一次修改的事件
ETag: "b00000000003b-d4-53cfa74f54144"   //有服务器生成的唯一标识
Accept-Ranges: bytes
Content-Length: 212 //数据的长度
//Content-Type:告诉客户端浏览器我给你的数据的类型
Content-Type: text/html//我告诉客户端浏览器我是一个文本,html

Content-Type:响应资源的MIME类型
MIME是标识文件类型的,文件后缀并不能正确无误的标识文件的类型。
思考?客户端与服务器间传递数据时,是以什么形式传输的?
客户端与服务器在进行数据传输的时候都是以字节形式进行的,咱们可以理解成是以文本形式传输,这时浏览器就需要明确知道该怎么样来解析这些文本形式的数据,MIME就是明确告知浏览器该如何来处理。

常见的有200代表成功、304文档未修改、403没有权限、404未找到、500服务器错误

get请求个post请求的区别

  • get 提交没有请求体,
  • get 提交发送到服务器端的请求的数据都在地址栏当中
  • 不安全,因为get 提交发送到服务器的数据都在地址栏当中
  • 所以请求发送的数据的大小有限制.

  • post 有请求体,请求体的数据就是客户端发送到服务端的内容的参数数据.

  • post 提交的数据都在请求体当中,相对来说安全
  • post 提交对发送到服务器端的数据大小没有限制
  • post 提交必须有一个请求头
    Content-Type:application/x-www-form-urlencoded
    以后假设表单提交,如果说要发送中文,最好我们都使用post

调试工具

利用HTTP抓包工具在开发中可以帮我们进行调试,常用抓包工具HttpWatch、Fiddler、Charles、FireBug等
浏览器插件
Firebug、HttpWatch、chrome dev tools
代理软件
Charles、Fiddler