不会JS中的OOP,你也太菜了吧!(第一篇)
一、你必须知道的
1) 字面量
2) 原型
3) 原型链
4) 构造函数
5) 稳妥对象(没有公共属性,而且其方法也不引用this的对象。稳妥对象适合用在安全的环境中和防止数据被其它程序改变的时候)
二、开始创建对象吧
<1>: 首先来看两种最基本的创建对象的方法
1> 使用Object创建对象
var o = new Object(); o.sname = 'JChen___1'; o.showName = function(){ return this.sname; }
2> 使用对象字面量创建对象
var o = { name: 'JChen___2', getName: function(){ return this.name; } }
但是这两个方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码。
<2> 接下来看看几种创建对象的模式吧
1>工厂模式
function create(name){ var o = new Object(); o.name = name; o.sayName = function(){ return this.name; }; return o; } var p1 = create('JChen___');
工厂模式也有一个缺点:就是没有解决对象识别的问题(即怎样知道一个对象的类型)。
2> 构造函数模式
function create2(name){ this.name = name; this.sayName = function(){ return this.name; }; //this.sayName = sayName; } //function sayName(){ return this.name}; var p1 = new create2('JChen___4');
构造函数模式也有一个缺点:就是每个方法都要在每个实例上创建一遍。
当然我们可以用上面的两行注释掉了代码来屏蔽上面那个缺点。
但是……,我们又产生了一个新问题——全局变量。如果有很多方法,我们岂不是要定义很多个全局变量函数。这是个可怕的问题。
3> 原型模式
1) 普通方法
function create3(){} create3.prototype.name = 'JChen___5'; create3.prototype.sayName = function(){ return this.name; }; var p1 = new create3();
2) 原型字面量方法——我姑且这么称吧
function create3(){} create3.prototype = { constructor: create3, //我们要设置它的constructor,如果它很重要 name: 'JChen___5', sayName: function(){ return this.name; } }; var p1 = new create3();
原型的缺点:
1): 不能传参
2): 共享了变量
4> 构造+原型(模式)
function create4(name){ this.name = name; } create4.prototype.sayName = function(){ return this.name; } var p1 = new create4('JChen___6');
这种模式是目前使用最广泛、认同度最高的一种创建自定义类型的方法。
5> 动态原型模式
function create5(name){ this.name = name; if(typeof this.sayName != 'function'){ create5.prototype.sayName = function(){ return this.name; } } } var p1 = new create5('JChen___7');
这种方法确实也是十分完美的一种方法。
6> 寄生构造函数模式
function create6(name){ var o = new Object(); o.name = name; o.sayName = function(){ return this.name; } return o; } var p1 = new create6('JChen___8');
注意那个return o。构造函数在不返回值的情况下,会返回新对象实例。而通过在构造函数的末尾加入return 语句,可以重写调用构造函数时返回的值。
这个种用法可以用在,假设我们想创建一个具有额外方法的特殊数组。由于不能直接修改Array的构造函数,因此可以使用这个模式。
function specialArray(){ var values = new Array(); values.push.apply(values, arguments); values.join2 = function(){ return this.join('|'); }; return values; } var colors = new specialArray('red', 'blue', 'green'); colors.join2();//returned: red|blue|green
7>稳妥构造函数模式
稳妥构造函数遵循与寄生构造函数类似的模式,但是有两点不同:
一是新创建对象的实现方法不引用this
二是不使用new操作符调用构造函数。
function create7(name){ var o = new Object(); var age = 12; //私有变量 o.sayName = function(){ //私有方法 return name + ' ' + age; } return o; } var p1 = create7('JChen___9');
三、总结
对象(类)的创建方法大概就这9种了吧。
创建是没问题了,但是这是第一步,如何实现继承呢?且看下回分解。
Block formatting context(块级格式化上下文)
今天看到豆瓣面试官的一篇文章,讲到关于CSS中的一个知识点:Block formatting context ,感觉这个确实挺有用,同时我也挺赞同作者的一些观点的,这里就不展开谈我的感受了, 此文只聊聊技术。
1.什么是Block formatting context?
Block Formatting Context提供了一个环境,HTML元素在这个环境中按照一定规则进行布局。一个环境中的元素不会影响到其它环境中的布局,就是说处在于不同Block Formatting Context环境中的元素是互不侵犯的。
2.Block formatting context的触发条件?
- the root element or something that contains it
- floats (elements where
float
is notnone
) - absolutely positioned elements (elements where
position
isabsolute
orfixed
) - inline-blocks (elements with
display
: inline-block
) - table cells (elements with
display
: table-cell
, which is the default for HTML table cells) - table captions (elements with
display
: table-caption
, which is the default for HTML table captions) - elements where
overflow
has a value other thanvisible
- flex boxes (elements with
display
: flex
orinline-flex
)
3.Block formatting context有什么用?
-
Block Formatting Context可以阻止边距折叠(margin collapsing)。我们知道在一般情况下,两个上下相邻的盒子会折叠它们垂直方向接触到的边距,这种情况只会发生在同一个Block Formatting Context中。换句话说,在同一个布局环境中(Block Formatting Context)是边距折叠的必要条件。这也就是为什么浮动的元素和绝对定位元素不会发生边距折叠的原因(当然还有很多种情况也不会折叠)。
*{margin:0; padding:0} body{width:100px;} #one, #two{ float:left; /*去掉float:left上下div的之间的间距将折叠为10px*/ width:100px; height:100px; margin:10px; } #one{ background:red; } #two{ background:blue; } <div id="one"></div> <div id="two"></div>
调试请猛戳这里
- Block Formatting Context可以包含内部元素的浮动。
<style type="text/css"> html, body { margin: 0; padding: 0; } #red, #orange, #yellow, #green { width: 100px; height: 100px; float: left; } #red { background: red; } #orange { background: orange; } #yellow { background: yellow; } #green { background: green; } </style> <div id="c1"> <div id="red"></div> <div id="orange"></div> </div> <div id="c2"> <div id="yellow"></div> <div id="green"></div> </div>
在上面的代码本意是做一个两行两列的布局,但是由于#red, #orange, #yellow, #green这四个div同在一个布局环境中,即便通过#c1, #c2这两个div划分,浮动之后它们还会一个接着一个排列,并不会换行。我们要做的就是把这四个div两两划分到不同的布局环境之中,从而闭合浮动。通过上面的分析,让#c1形成新的Block Formatting Context就可以解决问题。
调试请猛戳这里
- Block Formatting Context可以阻止元素被浮动覆盖
这个就是上面提到的豆瓣的面试官用到的一个特性,我们来看一个实例:
<!DOCTYPE html> <html> <head> <title>Demo</title> <style type="text/css"> html, body { margin: 0; padding: 0; } #left { width: 100px; height: 100px; background: red; float: left; } #right { overflow:hidden; height: 200px; background: yellow; } </style> </head> <body> <div id="left"></div> <div id="right"></div> </body> </html>
调试请猛戳这里
知道这个特性之后再来看豆瓣面试官的demo就清楚为什么会这样了!
=======================================
参考资料: