This commit is contained in:
qianguyihao 2018-03-06 22:22:25 +08:00
parent c3723f5dc2
commit 263943371e
5 changed files with 503 additions and 19 deletions

View File

@ -0,0 +1,269 @@
## 常见概念
- 构造函数
- 构造函数-扩展
- 原型规则和示例
- 原型链
- instanceof
## 构造函数
任何一个函数都可以被newnew了之后就成了构造方法。
如下:
```javascript
function Foo(name, age) {
this.name = name;
this.age = age;
//retrun this; //默认有这一行。new一个构造函数返回一个对象
}
var fn1 = new Foo('smyhvae', 26);
var fn2 = new Foo('vae',30); //new 多个实例对象
```
与普通函数相比,构造函数有以下明显特点:
- 用new关键字调用。
- 不需要用return显式返回值的默认会返回this也就是新的实例对象。
- 建议函数名的首字母大写,与普通函数区分开。
参考链接:
- [JavaScript中的普通函数与构造函数](http://www.cnblogs.com/SheilaSun/p/4398881.html)
当new之后this会先变成一个空对象然后通过`this.name = name`来赋值。
### 构造函数的扩展
20180306_1633.png
上图中发现数组、对象、函数也有构造函数它们的构造函数是Array、Object、funtion。实际开发中都推荐前面的书写方式。
## 原型规则
原型规则是学习原型链的基础。原型规则有五条,下面来讲解。
### 规则1
所有的引用类型(数组、对象、函数),都具有对象特性,都可以**自由扩展属性**。null除外。
举例:
20180306_1651.png
### 规则2
所有的**引用类型**(数组、对象、函数),都有一个`_proto_`属性,属性值是一个**普通的对象**。`_proto_`的含义是隐式原型。
20180306_1656.png
其实规则2是规则1的特例只不过js语法帮我们自动加了 规则2。
### 规则三
所有的**函数**(不包括数组、对象),都有一个`protype`属性,属性值是一个**普通的对象**。`protype`的含义是**显式原型**。(实例没有这个属性)
20180306_1659.png
### 规则四
所有的**引用类型**(数组、对象、函数),`_proto_`属性指向它的**构造函数**的`protype`值。
20180306_1701.png
总结:以上四条,要先理解清楚,然后再来看下面的第五条。
### 规则五
当试图获取一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的`_proto_`中寻找(即它的构造函数的`protype`)。
`举例代码1`
```javascript
//创建方法
function Foo(name) {
this.name = name;
}
Foo.prototype.alertName = function () {// 既然 Foo.prototype 是普通的对象,那也允许给它添加额外的属性 alertName
console.log(this.name);
}
var fn = new Foo('smyhvae');
fn.printName = function () {
console.log(this.name);
}
//测试
fn.printName(); //输出结果smyhvae
fn.alertName(); //输出结果smyhvae
```
上方代码中,虽然 alertName 不是 fn 自身的属性,但是会从它的构造函数的`protype`里面找。
**扩展:**遍历循环对象自身的属性
我们知道,`for ... in`循环可以遍历对象。针对上面的那个fn对象它自身有两个属性`name`、`printName`,另外从原型中找到了第三个属性`alertName`。现在如果我们对fn进行遍历能遍历到两个属性还是三个属性呢
答案:两个。因为,**高级浏览器中已经在 `for ... in`循环中屏蔽了来自原型的属性。但是,为了保证代码的健壮性,我们最好自己加上判断**,手动将第三个属性屏蔽掉:
```javascript
for (var item in fn) {
if (fn.hasOwnProperty(item)) {
console.log(item);
}
}
```
## 原型链
还是拿上面的``举例代码1``举例,如果此时在最后面加一行代码:
```
fn.toString(); //去 fn._proto_._proto 中查找 toString()方法
```
上面的代码中fn直接调用了 toString()方法,这是因为它通过**原型链**,去`_proto_`的`_proto_`里找到了`Object`,而`Object`是由`toString()`方法的。
### instanceof
格式:
```javascript
对象 instanceof 构造函数
```
`instanceof`的作用:用于判断**引用类型**属于哪个**构造函数**。
例1判断一个变量是否为数组 `变量 instanceof Array`
例2
```javascript
function Person(){
}
//p--->Person.prototype--->Object.prototype--->null
var p = new Person();
//构造函数的**原型**是否在 p 对象的原型链上!
console.log(p instanceof Person);
```
例3
```javascript
fn instanceof Foo
```
上面这句话,判断逻辑是:**fn 的`_proto_`一层一层往上找,看能否对应到 Foo.prototype**。
原型链如下:(重要)
20180306_1853.png
注意Object这个构造方法的显式原型是null这是一个特例。
## 常见题目
- 如何准确判断一个变量时数组类型
- 写一个原型链继承的例子
- 描述 new 一个对象的过程
- zepto(或其他框架)源码中如何使用原型链
下面分别讲解。
### 题目一:如何准确判断一个变量时数组类型
答案:
```javascript
var arr1 = [];
console.log(arr1 instanceof Array); //打印结果true。
console.log(typeof arr1); //打印结果object。提示typeof 方法无法判断是否为数组
```
上方代码表明,只能通过 instanceof 来判断是否为数组。而 typeof 的打印结果是 object。
### 题目二:写一个原型链继承的例子
来看个基础的代码:
20180306_1931.png
上面这个例子是基础,但是,在回答面试官的问题时,不要写上面的例子。要写成下面这个例子:(更贴近实战)
**举例:**写一个封装DOM查询的例子
> 这个例子有点像 jQuery 操作DOM节点。
表示这个例子,略难。
### 题目三:描述 new 一个对象的过程
1创建一个新对象
2this 指向这个新对象
3执行代码对this 赋值)
4返回this
参考链接:
- [原型、原型链、继承模式](https://my.oschina.net/u/2600761/blog/1524617)
```javascript
```

View File

@ -43,7 +43,7 @@
问题假设高度默认100px 请写出三栏布局其中左栏、右栏各为300px中间自适应。 问题假设高度默认100px 请写出三栏布局其中左栏、右栏各为300px中间自适应。
20180305_1520.png ![](http://img.smyhvae.com/20180305_1520.png)
分析: 分析:
@ -206,7 +206,7 @@
效果如下: 效果如下:
20180305_1640.gif ![](http://img.smyhvae.com/20180305_1640.gif)
### 方法3、flexbox布局 ### 方法3、flexbox布局
@ -280,7 +280,7 @@
效果如下: 效果如下:
20180305_1700.gif ![](http://img.smyhvae.com/20180305_1700.gif)
@ -358,7 +358,7 @@
``` ```
20180305_1855.gif ![](http://img.smyhvae.com/20180305_1855.gif)
### 方法5、网格布局 grid ### 方法5、网格布局 grid
@ -424,8 +424,7 @@
效果: 效果:
20180305_1920.gif ![](http://img.smyhvae.com/20180305_1920.gif)
### 延伸:五种方法的对比 ### 延伸:五种方法的对比
@ -485,7 +484,7 @@ PS面试提到网格布局说明我们对新技术是有追求的。
### 页面布局的变通 ### 页面布局的变通
20180305_1931.png ![](http://img.smyhvae.com/20180305_1931.png)
`上下高度固定,中间自适应`,这个在移动端的页面中很常见。 `上下高度固定,中间自适应`,这个在移动端的页面中很常见。

View File

@ -114,10 +114,9 @@ DOM事件流讲的就是浏览器在于当前页面做交互时这个事
- 3冒泡从**目标元素**传到 Window 对象。 - 3冒泡从**目标元素**传到 Window 对象。
![](http://img.smyhvae.com/20180204_1028.gif) ![](http://img.smyhvae.com/20180306_1058.png)
![](http://img.smyhvae.com/20180204_1218.jpg)
20180306_1058.png
## 描述DOM事件捕获的具体流程 ## 描述DOM事件捕获的具体流程
@ -127,7 +126,7 @@ DOM事件流讲的就是浏览器在于当前页面做交互时这个事
### 捕获的流程 ### 捕获的流程
20180306_1103.png ![](http://img.smyhvae.com/20180306_1103.png)
**说明**捕获阶段事件依次传递的顺序是window --> document --> html--> body --> 父元素、子元素、目标元素。 **说明**捕获阶段事件依次传递的顺序是window --> document --> html--> body --> 父元素、子元素、目标元素。

View File

@ -67,7 +67,7 @@ http协议的头部有一个`数据类型`通过http协议就可以完成
## HTTP报文的组成部分 ## HTTP报文的组成部分
20180306_1400.png ![](http://img.smyhvae.com/20180306_1400.png)
在回答此问题时,我们要按照顺序回答: 在回答此问题时,我们要按照顺序回答:
@ -79,7 +79,7 @@ http协议的头部有一个`数据类型`通过http协议就可以完成
### 请求报文包括: ### 请求报文包括:
20180228_1505.jpg ![](http://img.smyhvae.com/20180228_1505.jpg)
- 请求行包括请求方法、请求的url、http协议及版本。 - 请求行包括请求方法、请求的url、http协议及版本。
@ -91,7 +91,7 @@ http协议的头部有一个`数据类型`通过http协议就可以完成
### 响应报文包括: ### 响应报文包括:
20180228_1510.jpg ![](http://img.smyhvae.com/20180228_1510.jpg)
- 状态行http协议及版本、状态码及状态描述。 - 状态行http协议及版本、状态码及状态描述。
@ -128,7 +128,7 @@ head 可能偶尔用的到。
## get 和 post的区别 ## get 和 post的区别
20180306_1415.png ![](http://img.smyhvae.com/20180306_1415.png)
区别有很多,如果记不住,面试时,至少要任意答出其中的三四条。 区别有很多,如果记不住,面试时,至少要任意答出其中的三四条。
@ -151,11 +151,11 @@ head 可能偶尔用的到。
http状态码分类 http状态码分类
20180306_1430.png ![](http://img.smyhvae.com/20180306_1430.png)
常见的http状态码 常见的http状态码
20180306_1431.png ![](http://img.smyhvae.com/20180306_1431.png)
部分解释: 部分解释:
@ -170,7 +170,7 @@ http状态码分类
- 304我这个服务器告诉客户端你已经有缓存了不需要从我这里取了。 - 304我这个服务器告诉客户端你已经有缓存了不需要从我这里取了。
20180306_1440.png ![](http://img.smyhvae.com/20180306_1440.png)
400和401用的不多。403指的是请求被拒绝。404指的是资源不存在。 400和401用的不多。403指的是请求被拒绝。404指的是资源不存在。
@ -209,7 +209,6 @@ http状态码分类
管线化就是,我把现在的请求打包,一次性发过去,你也给我一次响应回来。 管线化就是,我把现在的请求打包,一次性发过去,你也给我一次响应回来。
### 管线化的注意事项 ### 管线化的注意事项

View File

@ -2,6 +2,17 @@
## 前言 ## 前言
### 面向对象的三大特性
- 封装
- 继承
- 多态
### 原型链的知识
原型链是面向对象的基础,是非常重要的部分。有以下几种知识: 原型链是面向对象的基础,是非常重要的部分。有以下几种知识:
- 创建对象有几种方法 - 创建对象有几种方法
@ -14,4 +25,211 @@
## 创建对象有几种方法
### 方式一:字面量
```javascript
var obj11 = {name: 'smyh'};
var obj12 = new Object(name: `smyh`);
```
上面的两种写法是一样的。因为,第一种写法,`obj11`会指向`Object`。
### 方式二:通过构造函数
```javascript
var M = function (name) {
this.name = name;
}
var obj3 = new M('smyhvae');
```
### 方法三Object.create
```javascript
var p = {name:'smyhvae'};
var obj3 = Object.create(p);
```
第三种方法,很少有人能说出来。
## 原型、构造函数、实例,以及原型链
20180306_1538.png
PS任何一个函数如果在前面加了new那就是构造函数。
### 原型、构造函数、实例三者之间的关系
20180306_2107.png
- 1、构造函数通过 new 生成实例
- 2、构造函数也是函数构造函数的`prototype`指向原型。(所有的函数有`prototype`属性,但实例没有 `prototype`属性)
- 3、原型对象中有 constructor指向该原型的构造函数。
上面的三行,代码演示:
```
var Foo = function (name) {
this.name = name;
}
var fn = new Foo('smyhvae');
```
上面的代码中,`Foo.prototype.constructor === Foo`的结果是`true`
20180306_2120.png
- 4、实例的`_proto_`指向原型。也就是说,`Foo._proto_ === M.prototype`。
声明:所有的**引用类型**(数组、对象、函数)都有`_proto_`这个属性。
`Foo._proto_ === Function.prototype`的结果为true说明Foo这个普通的函数是Function构造函数的一个实例。
### 原型链
**原型链的基本原理**:任何一个**实例**,通过原型链,找到它上面的**原型**,该原型对象中的方法和属性,可以被所有的原型实例共享。
Object是原型链的顶端。
原型可以起到继承的作用。原型里的方法都可以被不同的实例共享:
```
//给Foo的原型添加 say 函数
Foo.prototype.say = function () {
console.log('');
}
```
**原型链的关键**:在访问一个实例的时候,如果实例本身没找到此方法或属性,就往原型上找。如果还是找不到,继续往上一级的原型上找。
## `instanceof`的原理
20180306_2209.png
`instanceof`的**作用**:用于判断**引用类型**属于哪个**构造函数**。
`instanceof`的**原理**:判断实例对象的`_proto_`属性,和构造函数的`prototype`属性,是否指向同一个地址。
**注意**
1虽然说实例是由构造函数 new 出来的,但是实例的`_proto_`属性引用的是构造函数的`prototype`。实例的`_proto_`属性与构造函数本身无关。
2原型的上面可能还有原型以此类推往上走。这条链上 instanceof 的返回结果也是 true。
```javascript
```
```javascript
```
```javascript
```
```javascript
```
```javascript
```
```javascript
```