面向对象系列

1. 面向对象的三大特性

  1. 封装性: 将复杂的实现过程包装、隐藏起来,给用户提供使用接口。
  2. 继承性: 在js中,继承是体现在对象与对象之间的关系,继承就是指一个对象有权去访问别的对象上的成员。
  3. 多态性: 体现在子对象和父对象之间: 在父对象上的同一个行为,在各个子对象中的具体实现不同。

code show time:

code block:

1
2
3
4
5
6
var date = new Date;
console.log(date.toString());
var arr = [1, 3, 5];
console.log(arr.toString());
var o = {name: 'shelly'};
console.log(o.toString());

在这个里头你就可以看出相同的一个函数,在不同的调用结果就是不一样的,所以在js之中,多态就是 函数的重载和重写

2. 继承的实现方式:

  • 基于原型
  1. a: 扩展原型 : 在原有的原型上进行相应的扩展,实现继承。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    // 1>基于原型
    a: 基于原型: 扩展原型
    function A() {
    }
    var a = new A;
    A.prototype.printA = function() {
    console.log('a');
    };
    a.printA();// a
    a -> A.prototype
  2. b: 置换原型:将要被继承的对象,直接替换掉原有的原型,实现继承

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// b: 基于原型: 置换原型
function parent() {
this.name = 'tom';
}
parent.prototype.printC = function() {
console.log('c');
console.log(this.name);
};
function child() {
}
child.prototype = new parent;
var c = new child;
c.printC(); // c
// c -> parent实例 -> parent.prototype
var name = new child;
var name = [1, 2, 3];
console.log(typeof name);
// 全局变量都是window对象的属性
// window的name属性只能为字符串
  • 拷贝继承:
    将指定对象上的所有成员拷贝一份,并添加到当前对象上。这种继承方式成为拷贝继承。
    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
    // 2> 拷贝继承:将别的对象上的所有成员拷贝一份,添加到当前对象本身。
    var parent = {
    print: function() {
    console.log('i am ' + this.name);
    },
    name: 'parent'
    };
    var child = {
    name: 'child'
    };
    // 1: 遍历parent
    for (var k in parent) {
    // 2: 将parent对象上的成员添加到child上。
    child[k] = parent[k];
    }
    child.print();
    var parent1 = {
    print1: function() {
    console.log('print1');
    }
    };
    for (var k in parent1) {
    // 2: 将parent对象上的成员添加到child上。
    child[k] = parent1[k];
    }
    // 封装
    // 封装为child对象一个方法extend,谁调用extend方法就是给谁实现继承。
    child.print1();

非常的麻烦所以就有了extend

  • 对象冒充: 在一个构造函数中,可以动态的添加一个parent方法,指向已有的构造函数,然后掉用parent方法去实例化当前对象的
    一部分成员(或全部成员)。此时这种方式被称为对象冒充。
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    function parent(name, age, gender) {
    this.name = name;
    this.age = age;
    this.gender = gender;
    }
    function child(name, age, gender, address) {
    this.parent = parent;
    this.parent(name, age, gender);
    delete this.parent;
    this.address = address;
    }
    var c = new child('xiaoming', 20, 'girl', 'china');
    console.log(c);

注意 :利用完parent属性之后,记得删除该属性。
在实际开发中,两种继承方式可以组合起来应用。

3. extend方法的实现: 为了方便去实现拷贝继承。

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
38
1: 一次只能继承一个对象
var child = {};
child.extend = function(parent) {
var k;
for( k in parent ){
this[k] = parent[k];
}
};
child.extend({
name: 'child',
print: function() {
console.log(this.name);
}
});
child.print();
2: 一次实现继承多个对象
child.extend = function() {
var args = arguments,
obj;
// 遍历arguments上的所有对象,依次将遍历的每个对象的成员添加到child。
for( var i = 0, l = args.length;i < l; i++){
obj = args[i];
if( typeof obj === 'object'){ // 判断传入的是否为对象,不是对象就不执行下面代码
for( var k in obj ){
this[k] = obj[k];
}
}
}
};
child.extend({
name: 'child'
}, {
print: function() {
console.log('i am ' + this.name);
}
});
child.print();

4. ES5 Object.create : 通过置换原型的方式来实现继承。

1
2
Object.create(parent)://返回值为一个新的对象,并且该对象继承自parent对象。
var newObject = Object.create(parent);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 兼容问题:
if( !Object.create ){
Object.create = function(parent) {
function F() {}
F.prototype = parent;
return new F;
}
}
var newobj = Object.create({
name: 'tom',
print: function() {
console.log(this.name);
}
});
newobj.print();

5. 原型链的概念

  1. 几个默认
  • a: 所有对象都有proto属性,这个属性引用它的原型对象。
  • b: 原型对象继承自Object.prototype,具有constructor属性;如果置换了原型,记得要添加constructor属性。
  • c: 只有函数具有prototype属性(除了Function.prototype)。
  1. 概念:从当前对象到Object.prototype之间,存在一条层次分明,逐级递进的体现继承关系的链式结构
    == 这个结构被称为原型链。==

6. 属性搜索原型: 当访问对象成员时

    • 首先,在当前对象上查找,如果找到就直接返回(调用),停止查找;
    • 如果没有找到,就向其原型对象上查找;如果找到就直接返回(调用),停止查找;
    • 如果没有找到,就继续向原型对象的原型对象上查找,直到Object.prototype;
    • 如果找到,那么就直接返回(调用),并停止查找;否则返回undefined(报错:xxx is not a function)

*注意

- 如果访问对象的某个属性不存在的话,会搜索整个原型链。会导致js性能降低。
- 在实际开发中,尽量保持一个适度的原型链长度。
- 兼顾js性能以及代码的可读性可扩展性。

7. Object.prototype介绍

  1. hasOwnProperty:判断当前对象的指定属性是否为自身的,而不是继承过来的;如果是本身的返回true;否则返回false。

    1
    2
    3
    4
    5
    6
    7
    语法:<object>.hasOwnProperty('propName')
    has: 有
    own:自己
    Property : 属性
    var o = {name: 'tom'};
    console.log(o.hasOwnProperty('name')); // true
    console.log(o.hasOwnProperty('toString')); // false
  2. isPrototypeOf:判断当前对象是否为指定对象的原型对象。如果是返回true;否则返回false。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    语法;<a>.isPrototypeOf(<b>);
    <!-- 只要对象a出现在b对象的原型链上就返回true;否则返回false。 -->
    function A() {
    }
    function B() {
    }
    var a = new A;
    B.prototype = a;
    var b = new B;
    console.log(a.isPrototypeOf(b)); // false;
    console.log( A.prototype.isPrototypeOf(b));
    // b -> a -> A.prototype -> Object.prototype -> null
    console.log(Object.prototype.isPrototypeOf(a));
    console.log(Object.prototype.isPrototypeOf(b));

    如果当前对象出现在指定对象的原型链上就返回true;否则返回false。

  3. propertyIsEnumerable:即判断指定属性是否为自身的,并且该属性也是可枚举的

    只有这两个条件都满足才返回true;否则返回false。
    
    • // 可枚举?for in遍历出来的属性都是可枚举的。
    • // 默认:手动添加属性都是可枚举的,js解析器自动添加的都是不可枚举。

8. 构造函数的执行过程

  1. 创建了一个空对象obj;
  2. 将obj赋值给this(让this指向obj)
  3. 将当前作用域交给this
  4. 执行构造函数内部的代码
  5. 将 this 返回。(return this;)
1
2
3
4
5
6
7
8
9
10
11
12
function Fn(name, age) {
this.name = name;
this.age = age;
}
var fn = new Fn('tom', 18);
console.log(fn);
function Fn(name, age) {
var obj = {};
this = obj;
// Fn.call(this, name, age);(这个可以替代上面的两句话)
return this;
}

9. 绘制对象的原型链

绘制规则:

  1. 绘制出简化的原型链
  2. 先将上述简化的原型链上的每一个对象绘制在图形上。
  3. 将每一个对象的默认属性添加上。
  4. 给每一个对象的属性添加指向。
  5. 如果每一个对象的属性都有了指向,说明原型链绘制完成。

如何理解原型?

不纠结任何术语,比如说:“人是人他妈生的,妖是妖他妈生的。”

1.人和妖都是对象,而人他妈和妖他妈就是构造函数,人他爸和妖他爸就是原型。

2.人他妈如何才能正确找到人他爸,而不会找错呢?答案就是prototype属性,人他妈可以通过这条线准确的找到自己的老公(人他爸)。同理,人他爸可以通过constructor属性准确的找到自己的老婆(人他妈)。

3.人他妈可以生很多的宝宝,但是这些宝宝只有一个粑粑。这就是原型的唯一性。

4.通过人可以找到人他爸,在通过人他爸找到人他爸他爸,…,这样一条链就叫做原型链。

5.原型链并不是无限无尽的,最终人他爸他爸…他爸不是人,而是null,也就是说最终原型链最终指向null。

6.人他妈生的人长的像人他爸的样子,妖他妈生的妖会像妖他爸那样丑陋,这就叫做继承。

7.人继承了人他爸的一切,人他爸继承了人他爸他爸的一切,…,这就是原型链继承。

8.人恋爱了,她妈让人拿着房产去提亲,人若没有,就问人他爸;人他爸没有,就会问人他爸他爸…,这就是属性搜索原型。

9.人继承了人他爸的发色,但是人可以来个洗剪吹。那么这就是说对象的属性可以自定义,会覆盖继承得到的属性。

10.即使人洗剪吹变成了黄毛怪,但也无法改变人他爸的发色。人他妈生的弟弟妹妹不会是黄毛怪,这就是说对象无法改变原型的属性。

11.人他爸爱嘚瑟,去趟泰国动个小手术又去趟韩国整个形,虽然还是人他爸,但相比从前,已是回炉再造啦。这就是原型的重写。也是原型的置换。

!!Code: show time!!

原型的特性

1、不可变性:对象无法修改其原型对象的任何成员

code block:
function A() {}
A.prototype.color = 'black';
var a = new A;
a.color = 'goldyellow';
var ad = new A;
console.log(ad.color); // black
console.log(A.prototype.color); // black
console.log(a.color); // goldyellow

2、唯一性:由同一函数创建出来的所有对象共享一个原型对象

function A() {}
A.prototype.color = 'black';
var a = new A;
var ad = new A;
console.log(a.__proto__ === ad.__proto__); // true
console.log(ad.color); // black
console.log(a.color); // black

3、动态性 (就是可以用点会或者是【】来调用)

<1

function A() {}
A.prototype.color = 'black';
var a = new A;
var ad = new A;
A.prototype.makefood = function (){ console.log('做饭饭.')}
a.makefood(); // 做饭饭
ad.makefood(); // 做饭饭

<2

function A() {}
A.prototype.color = 'black';
var a = new A;
A.prototype = {
constructor: A,
makeup: function() {
console.log('我会化妆.');
}
};
var na = new A;
console.log(a.color); // black
a.makeup();// 报错
na.makeup(); // 我会化妆.
console.log(na.color); // undefined

4、继承性:每一个对象都继承自它的原型对象

function A() {}
A.prototype.color = 'black';
var a = new A;
var na = new A;
console.log(a.color); // black
console.log(na.color);// black

css框架

code block:
随着Web应用变的越来越复杂,在大量的开发过程中我们发现有许多功能模块非常相似,比如轮播图、分页、选项卡、导航栏等,开发中往往会把这些具有通用性的功能模块进行一系列封装,使之成为一个个组件应用到项目中,可以极大的节约开发成本,将这些通用的组件缩合到一起就形成了前端框架。

1.1 Bootstrapcss框架

简洁、直观、强悍的前端开发框架,让web开发更迅速、简单。
来自 Twitter,粉丝众多,是目前最受欢迎的前端框架。

开始使用吧!

1.2 Amaze UI

Amaze ~ 妹子UI,国人开发,后起之秀!
开始使用吧!

1.3 Framework7

Framework7 是一个开源免费的框架可以用来开发混合移动应用(原生和HTML混合)或者开发 iOS & Android 风格的WEB APP。
开始使用吧!

网页布局

简单的提一下这个

各种布局

1.固定宽度布局:为网页设置一个固定的宽度,通常以px做为长度单位,常见于PC端网页。
2.流式布局:为网页设置一个相对的宽度,通常以百分比做为长度单位。

3.栅格化布局:将网页宽度人为的划分成均等的长度,然后排版布局时则以这些均等的长度做为度量单位,通常利用百分比做为长度单位来划分成均等的长度。

4.响应式布局:通过检测设备信息,决定网页布局方式,即用户如果采用不同的设备访问同一个网页,有可能会看到不一样的内容,一般情况下是检测设备屏幕的宽度来实现。

注:以上几种布局方式并不是独立存在的,实际开发过程中往往是相互结合使和的。

响应式布局

如上图所示,屏幕尺寸不一样展示给用户的网页内容也不一样,我们利用媒体查询可以检测到屏幕的尺寸(主要检测宽度),并设置不同的CSS样式,就可以实现响应式的布局。
我们利用响应式布局可以满足不同尺寸的终端设备非常完美的展现网页内容,使得用户体验得到了很大的提升,但是为了实现这一目的我们不得不利用媒体查询写很多冗余的代码,使整体网页的体积变大,应用在移动设备上就会带来严重的性能问题。
响应式布局常用于企业的官网、博客、新闻资讯类型网站,这些网站以浏览内容为主,没有复杂的交互。
常见的设置宽度:

  • 大屏幕:大于等于1200px
  • 默认: 大于等于980px
  • 平板: 大于等于768px
  • 手机到平板:小于等于767px
  • 手机: 小于等于480px
    用来设置媒体查询。