面向对象编程

封装

对象生成的原始模式

var Cat = {
    name  : '',
    color : ''
}

然后生成实例对象,

var cat1 = {};

cat1.name = '大毛';
cat1.color = '黄色';

var cat2 = {};

cat2.name = '二毛';
cat2.color = '黑色';

很简单,但问题是,这样生成的“实例对象”其实和原型对象之间基本没有任何联系。而且生成多个实例的时候,没有简洁的方法,会非常麻烦。

原始模式的改进

function Cat(name,color){
    return {
        name  : name,
        color : color
    }
}

然后生成实例对象,但其实就等于在调用函数,返回一个对象。

var cat1 = Cat('大毛','黄色');
var cat2 = Cat('二毛','黑色');

这种问题是,如果 Cat 中不进行额外的处理,这里仍旧不能反映出来 cat1 和 cat2 内在的联系。

构造函数模式

function Cat(name,color){
    this.name = name;
    this.color = color;
}

现在就可以生成实例对象了。

var cat1 = new Cat('大毛','黄色');
var cat2 = new Cat('二毛','黑色');

这时 cat1 和 cat2 会自动含有一个 constructor 属性,指向他们的构造函数。

console.log(cat1 instanceof Cat); //true
console.log(cat2 instanceof Cat); //true

但此时这种方式仍旧存在其固有的问题。假设这里有一个方法。

function Cat(name,color){
    this.name = name;
    this.color = color;
    this.type = '猫科动物';
    this.eat = function(){console.log('吃老鼠');}
}

生成实例

var cat = Cat('大毛','黄色');
console.log(cat.type); // 猫科动物
cat.eat(); // 吃老鼠。

表面上没什么问题,用的时候也很好用,但是假如我们需要生成大量的 Cat 的实例,那么每个实例都会有 type 属性和 eat 方法,而且这两个都是一摸一样的内容,导致了内存的浪费,因为此时两个实例的相同属性和方法,并不是同样的内存地址。会存在多份。

那么,能不能将所有的相同的属性和方法只存在一份,然后每个实例同样的也可以使用呢?答案肯定是可以的。

prototype 模式

function Cat(name,color){
    this.name = name;
    this.color = color;
}

Cat.prototype.type = '猫科动物';
cat.prototype.eat = function(){console.log('吃老鼠');}

这时候,

var cat1 = new Cat('大毛','黄色');
var cat2 = new Cat('二毛','黑色');

此时,再多的实例对象,其 type 属性和 eat 方法都指向的是同一份,也即相同的内存地址。

console.log(cat1.eat === cat2.eat); //true

prototype 模式的验证方法

为了配合 prototype 模式, javascript 定义了一些辅助方法,帮助我们更方便的使用它。

isPrototypeOf()

这个方法用来判断,某个 prototype 对象和某个实例之间的关系。

console.log(Cat.prototype.isPrototypeOf(cat1)); //true

hasOwnProperty()
次方法用来判断某个属性到底是prototype 对象的属性还是类定义的(本地属性)。

console.log(cat1.hasOwnProperty('name')); true
console.log(cat1.hasOwnProperty('type')); false

in 运算符

此运算符用来判断某个属性是不是存在于某个实例中,即某个实例是否包含某个属性,不管是本地还是继承自 prototype

console.log("name" in cat1); // true
console.log('type' in cat1); // true
console.log('typo' in cat1); // false

in 运算符还可以用来遍历对象的属性。

for(var key in cat1){
    console.log('cat1[' + key ' ]=' + cat1[key]);
}

当然在遍历的时候可以使用 hasOwnProperty() 来限制输出的属性。

vi  /usr/local/nginx/conf/nginx.conf

开头有一个

#user  nobody;

把井号删掉,nobody改为  用户名 [空格] 用户组,例如

user nginx  web;

即以web组的nginx用户来运行nginx.

修改完以后

/usr/local/nginx/sbin/nginx -s reload

重启nginx

注:具体重启的命令在具体的环境下有区别。所有的路径也一样,请注意。

来源:http://my.oschina.net/cxz001/blog/97206

var getCursorPositionOfPage = function(e){
    var x, y;
 
    e = e || window.event;
 
    x = e.pageX || (e.clientX + (document.documentElement.scrollLeft || document.body.scrollLeft));
    y = e.pageY || (e.clientY + (document.documentElement.scrollTop  || document.body.scrollTop));
 
    return {
        'x':x,
        'y':y
    };
};

使用方式:

document.querySelector("body").addEventListener("click",getCursorPositionOfPage ,false);

document.getElementsByTagName("body")[0].onmousemove = getCursorPositionOfPage ;

经过简单的测试,各个浏览器的差异如下:

 pageY       chrome/IE10/IE9/firefox29          随滚动条滚动而变化        页面高度   X 同理      IE8/IE7 未定义

 clientY     chrome/IE10/IE9/IE8/IE7/firefox29  不随滚动条滚动而产生变化   窗口高度   X 同理



 document.documentElement   chrome/IE10/IE9/IE8/IE7/firefox29     html

 document.body              chrome/IE10/IE9/IE8/IE7/firefox29     body
// 滚动条未滚动
 document.documentElement.scrollTop    chrome            0

 document.body.scrollTop               chrome            0

// 滚动条滚动
 document.documentElement.scrollTop    chrome            0

 document.body.scrollTop               chrome            100


// 滚动条未滚动
 document.documentElement.scrollTop    IE10/IE9/IE8/IE7/firefox29            0

 document.body.scrollTop               IE10/IE9/IE8/IE7/firefox29            0

// 滚动条滚动
 document.documentElement.scrollTop    IE10/IE9/IE8/IE7/firefox29            100

 document.body.scrollTop               IE10/IE9/IE8/IE7/firefox29            0

上面的 0 表示就是 0 ,100 表示有值。

兼容多种模块规范的 javascript 模块化写法

;(function(name,definition){
    
    var hasDefine  = typeof define === 'function',  // 检测上下文环境是否为 AMD 或者 CMD        
        hasExports = typeof module !== 'undefined' && module.exports;  // 检查上下文是否为 node

    if(hasDefine){
        define(definition); // AMD 或者 CMD 环境
    }else if(hasExports){
        module.exports = definition(); // 定义为普通 node 模块
    }else{
        this[name] = definition(); // 将模块的执行结果挂载在 window 变量中,在浏览器中 this 指向 window 变量。
    }

})('hello',function(){ // 此处 hello 只是作为模块化的示例名称
    var hello = function(){};
    return hello;
})

不过此种写法要保证前端引用或者后端使用没有全局的 define 函数覆盖 AMD 或者 CMD 的 define 函数。

此代码来源于 深入浅出Node.js P45 2.7.4,此处为记录以及熟悉。

在经过了IE6 IE7的洗礼之后,我们终于可以放心的使用 inline-block 了,但是在使用 inline-block 的时候,我们总会发现很多莫名其妙的空隙出现在两个 inline-block 元素之间,例如我们的代码如下所示:

<nav>
  <a href="#">One</a>
  <a href="#">Two</a>
  <a href="#">Three</a>
</nav>
nav a {
  display: inline-block;
  padding: 5px;
  background: red;
}

然后在浏览器里面的结果就是:

但是一般情况下,我们这么写,总是想让各个元素紧挨在一起的,如果需要中间有空隙,那我们可以通过 css 来更精确地控制。难道这个是一个 bug。刚刚好可以方便的使用这个属性值了,又出现 bug 了,难道又要骂娘了?

其实,了解了背后的原理,就明白这里其实并不是一个 bug,因为对浏览器来说,回车和换行都会被当做有效地字符,只是看不见而已,由于其被当做有效地字符,所以这个空隙的大小会随着定义的文字大小而改变,所以这里也就是为什么我们不需要它的出现,而要自己控制间隙的原因。那么既然知道了产生这个问题的原意,那就有解决方案来应对它。

方法一,可以通过代码来去掉这个inline-block 元素之间的空格。

<nav>
  <a href="#">
    One</a><a href="#">
    Two</a><a href="#">
    Three</a>
</nav>

或者

<nav>
   <a href="#">One</a
  ><a href="#">Two</a
  ><a href="#">Three</a>
</nav>

或者

<nav>
  <a href="#">One</a><!--
  --><a href="#">Two</a><!--
  --><a href="#">Three</a>
</nav>

然后,这就解决了这个问题,主要就是想办法去掉那个换行或者空格。但是这样子的话,会让我的结构很不好看,尤其是对于处女座的前端来说。

方法二:负边距

nav a {
  display: inline-block;
  margin-right: -4px;
}

此时需要给相应的元素以负边距来抵消产生的空隙,但是上面的原因说过了,由于跟其字体大小有关系,所以在具体的情况下,需要更具字体来调整。风险是,万一用户系统中没有你设定的字体呢?

方法三:不写结束标签

<ul>
  <li>one
  <li>two
  <li>three
</ul>

方法四:字体大小 0

由于空隙来源于字符,那我让他为 0 的大小不就行了?对嘛,真聪明。

nav {
  font-size: 0;
}
nav a {
  font-size: 16px;
}

不过,这样的方式,在某些平台以及某些浏览器上是有 bug 的。而且,如果使用 em 作为单位,那么下面的文字再怎么设置都是 0 了(em相对于父级)。

反正,每种方法都不算优雅,但基本都可以解决问题。

但或者,我们有可能根本就不需要 inline-block ,float 如果好用的话。或者以后可以用 flexbox 了。美好的愿望,在国内。

来源于:Fighting the Space Between Inline Block Elements 按自己的理解翻译,未忠实于原文。