Skip to content

374632897/just-some-tips

Repository files navigation

前端学习中积攒的一些小经验

2016-11-03 更新说明

这个项目已经很久没有更新了, 偶尔更新也是为了测试所用, 就README而言, 并没有怎么更。 想起这个工程是当初刚刚学了前端, 然后入职之后开来作为记录使用的, 最开始的时候更新很积极, 因为那个时候确实遇到了很多的问题, 而且有些非常基本的问题自己也会记录在这里。 然而当时记录的东西, 现在再来看的话 , 会发现很多错误。 自己一直比较忙(瞎说的), 也就没有腾出太多的时间用来重新审视, 最近觉得非常有必要, 所以就来看一看, 准备利用今天(周四)、周五、周末的时间, 把这里的东西重新整理一遍, 温故而知新, 相信重新整理后, 我应该能收获不少吧。 我将原来的那个重命名为README.PRE.MD, 权当留作纪念吧。

2015-12-10

  1. 在进行布局的时候,大多数情况下, 按照百分比来规定元件的宽高是比较好的。 至少在以后再做响应式的时候, 可以不用那么麻烦。

2015-12-11

  1. 如果在浏览器不同标签页里发现同一页面的呈现情况不一致。。。比如说屏幕本身宽度为1600px,但是审查元素的时 候,显示元素宽度和设定的宽度不一致,那么考虑是不是浏览器缩放所致 -- 笑cry

  2. 如果 npm install 的时候报错,则可以尝试以管理员身份运行, 或者使用cnpm安装, 或者o(╯□╰)o 有时候使用cnpm安装包以后, 项目跑不起来, 总是会说有几个包安装错误的话o(╯□╰)o , 那么再重新用npm装一遍吧。

2015-12-15

  1. new Date.getFullYear() 和 new Date().getFullYear()的问题
new Date.getFullYear(); // Uncaught TypeError: Date.getFullYear is not a constructor(…)
new Date().getFullYear(); // 2016
(new Date).getFullYear(); // 2016
(new Date()).getFullYear(); // 2016

也就是说,其实这里因为new Date的时候没有带参数, 所以new 的优先级要低于.``的优先级, 因此会先尝试访问``Date.getFullYear``, 但是这样得到的结果是undefined`,然后再执行new,由于undefined不是构造函数, 所以就会报错了。 因此当给``new Date``加上括号之后, 提升了语句的优先级, 就不会报错了。 圆括号的优先级是最大的。而至于这里带不带括号的问题, 其实无关紧要, 在需要传递参数的时候自然需要带括号, 如果不传递参数, 可以不带。 附: 运算符优先级

  1. 静态类型语言指的是在编译的时候就已经能够确定变量的值的类型的语言,动态类型语言是指在执行的时候才能确定 类型的语言,也就是在变量被赋值之后才能确定其类型。

  2. 多态的思想实质上是把做什么和谁去做分离开来。

  3. 自调用函数的写法的区别:

    (function () {console.log('hello'})();
    (function () {console.log('hello'}());
    !function () {}();
    +function () {}();

    这里代表函数执行的括号写在内部和写在外部的区别是什么?

  4. JS 数据封装

var myObject = (function () {
  var _name = 'hello';
  return {
    getName: function (){
        return _name;
    },
    setName: function (value){
       _name = value;
    }
  };
 }());

原理:定义一个变量为一个函数的返回值,在这个函数内部,定义了私有变量,在函数的返回值里,对外提供两个方 法来获取值和设置该私有变量,这样,就形成了私有接口和公共接口。

2015-12-16

  1. 使用new操作符调用函数时,返回的是一个对象,构造器里的this就指向这个对象, 如果构造器里会返回一个对象, 那么最终生成的对象会是返回的对象, 如果返回的不是对象, 而是基本 类型, 那么生成的对象将不会收到返回值影响。
var A = function () {
  this.name = 'Jason';
  this.age = 22;
  return {
    name: 'Daisy',
    age: 21
  };
}
var a = new A();
a // Object {name: "Daisy", age: 21}

var S = function () {
  this.name = 'Jason';
  return 'Daisy';
}
new S(); // S {name: "Jason"}

在这里有一个需要注意的地方是, 在上面的构造函数里面返回一个对象的时候, 那么这个返回的对象的构造器并不是A, 而是Object, 也就是说当在一个函数里返回了一个引用类型的值之后, 那么对这个函数使用new操作符的话获取到的将会是返回的这个对象, 并且且构造器是该对象的包装类型。

const obj = {
  name : 'JGX',
  detail: {
    gender: 'male',
    age: 22,
    favor: 'read',
    saySth () {
      console.log('inner')
    }
  }
}
const detail = obj.detail;
detail.age = 22;
obj.detail.age; // 22  // 也就是说在这里通过对象的引用对其属性的修改反应在了原对象的内部
let func = obj.detail.saySth; // 此时func指向的是obj.detail.saySth在内存中的地址
func = () => { // 重新给func赋值, 也就是说此时的func指向的是后面的函数在内存中的地址, 而与上面的obj.detail.saySth失去了关联
  console.log('outer')
};
func(); // outer
obj.detail.saySth(); // inner // 上面重写了func之后并没有反应在源对象上。

2015-12-17

  1. Maximum call stack size exceeded错误发生一般都是因为递归的时候没有设定终止条件, 使得函数一直在自调用从而造成了调用栈溢出。

  2. 通过获取label的引用,再调用它的control属性,即可获取到与之关联的元素

  3. 关于函数bind方法的实现:

Function.prototype._bind = function(context) {
  var self = this;
  return function () {
    return self.apply(context,arguments);
  }
};

2015-12-18

  1. View要实例化以后才行。

  2. 关于闭包,先看下面一段代码

var func = function () {
  var a=6;
  return function () {
    return a;
  }
};

var f = func();
f(); // 6

在这里把f指向func的运行结果,而func的运行结果也就是返回一个函数,从而使得f变成了匿名函数的引用,因此,当调用f()时,就会执行该匿名函数,因为该匿名函数是在func内部的,而匿名函数内部又会返回外层函数的a值,从而使得我们可以在func函数的外部获取到func函数内部的值。

2015-12-19

  1. Array.prototype.push === [].push //true 后面跟有方法的时候就为true,没有跟方法,则为false。 因为这里在访问[]push方法的时候, 实际上是走Array的原型里查找的, 所以这个时候[].push就等于Array.prototype.push了。

  2. 突然就扯到关于原型上的东西了,还是做点笔记吧

    • object.constructor: 表示object的构造器

      var ary = [];
      ary.constructor === Array;// true;

      因为ary是Array的实例,所以它的constructor 就指向了它的构造函数Array;

    • function定义的对象有一个prototype属性,而new生成的对象则没有这个属性

      var Hello = function () {
        this.name = 'Jason';
        this.sayName = function () {
          console.log(this.name);
        }
      };
      
      var hello = new Hello();

      当对一个函数使用new操作符的时候,会生成一个对象。对象里面的属性和方法会与其构造器中有this的相关联。

      Hello.prototype.constructor就等于Hello本身

      而hello.constructor也等于Hello,但是,Hello.prototype 与hello是不等的,因为Hello.prototype是Hello的原型对象,而hello是Hello的实例对象。

    • function 的prototype属性指向prototype对象,而prototype对象的constructor属性,又指向function 本身。 所以上面提到的那个问题就有解了。Array.prototype指向的是它的原型对象,原型对象里面封装了一系列的方法,而ary则是Array的一个实例,那么,这个实例就从原型链上继承了对应的方法,所以说,Array.prototype.slice === [].slice

    • 那么再重新理一理 关于Array.prototype.slice === [].slice

      • Array.prototype.slice是原型对象里封装的一个slice方法
      • []相当于是new 了一个Array,也就是生成了一个Array的实例。
      • 那么当使用到[].slice方法的时候,由于它本身并没有这个方法,所以就会走原型链上查找,于是在其构造器的原型对象中找到了这个方法,所以说,他们是相等的喃。
      • 现在理清之后感觉好简单,之前却一直没搞懂o(╯□╰)o 果然是人太笨了
    • 注意区分定义对象的属性和定义构造函数

      //定义对象
      var person = {
        name: 'Jason',
        sayName: function () {
          console.log(this.name);
        }
      };
      
      //定义构造函数
      var Person = function (){
        this.name = 'Jason';
        this.sayName = function () {
          console.log(this.name);
        };
      };

2015-12-20

  1. 构造函数的实例具有[[Prototype]]内部属性,可以把该属性理解为指向其构造函数的原型对象的指针。谷歌、FF、Safari提供了_proto_。需要注意的是,在所有实现中都无法访问到[[Prototype]],但是可以通过Person.prototype.isPrototypeOf(person)来确定对象之间是否存在这种关系。proto(注意是__而不是_, 也就是说,是两条下划线而不是一条)是存在于实例和构造函数的原型对象之间而不是实例和构造函数之间 。

  2. 函数柯里化

    • 基本方法:使用一个闭包返回一个函数,当函数被调用时,返回的函数还需要设置一些传入的参数

2015-12-21

  1. 关于使用inline-block进行居中
  • 对父元素设置text-align:center;
  • 对子元素设置display:inline-block;
  • 这样子的话,即使子元素里面有块级元素,那么该块级元素也不会充满整行 o(╯□╰)o 怎么说呢,感觉就像是里面的块级元素也被设置了inline-block一样,但是事实上他们的display依然是block;
  • 这个方案的缺点就是text-align默认是个继承属性,所以如果其子孙元素的text-align值不符合的话,还要单独写。
  • 另外一个需要注意的地方是,inline-block元素会存在一个1像素或者多个像素的间距, 所以如果对子元素设置了100 / 子元素数量 的百分比宽度后, 最后会被挤下去。 解决办法是给父元素设置font-size: 0;, 然后再对子元素设置font-size属性。
  • 此外, inline-block默认对齐方式为基线对齐, 通常需要手动改为top, 也就是vertical-align: top;

2015-12-22

  1. 在添加监听事件时,回调函数不能加括号,如:

    this.listenTo(this.model, 'change', this.render)

    加括号是不行的, 因为加了括号后, 那么第三个参数将会是该函数的执行结果, 而不一定是一个函数。

2015-12-23

  1. 逻辑是否正确是找出问题的关键。出错的时候,需要考虑是不是自己的逻辑设计不合理
  2. 如果点击一个元素出现了不期望的行为,则考虑是不是事件冒泡引起的。e.stopPropagation()
  3. 待整理 函数节流的实现

var throttle = function (fn,interval) {
 var _self = fn,
     timer,
     firstTime = true;
 return function () {
   var args = arguments, // event
       _me  = this;      // window
   // 如果是第一次,就直接执行函数
   if (firstTime) {
     _self.apply(_me,args); // 相当于在me 的环境下执行 _self(args){}函数
     // _self();
     return firstTime = false;
   }

   // 如果定时器还在,就return false;
   if (timer) {
     return false; // return false之后,就是不执行后面的语句了,感觉这里应该直接return就行的
   }

   timer = setTimeout(function () {
     clearTimeout(timer);
     timer = null;
     _self.apply(_me,args);

   }, interval || 500);
 };
};

window.onresize = throttle(function () {
 console.log(1);
});

在搞懂这段代码之前,先来弄清几个东西,如下:

function log () {
 console.log('hello');
}
document.onclick = function () {
 log();
}; // hello
  • 第一种情况下,把log()放在另一个函数里,当发生click事件的时候会在这个函数里面执行log,因为函数加了括号就表示这个函数的执行结果而不是指向函数的引用。而函数的执行结果就是记录下hello。

document.onclick = function () {
  log;
}; // 无反应
  • 第二种情况下,直接把log放在函数里,这样其实没有什么意义,这就相当于把一段代码放进去,但是代码本身并没有触发条件

document.onclick = log(); // 语句执行到这里的时候直接log;之后点击无反应
  • 第三种情况下,直接把log()的执行结果绑定到onclick上,但是这本身是没有意义的,因为这里的执行结果是一个单独的语句而不是函数。所以当语句执行到这里的时候,就直接执行了log(),而因为这个绑定是无效的,所以document.onclick = null;之后再点击也没有反应了. 当然,如果log的返回值是一个函数的话, 那么document上的绑定事件则会加在这个函数上。

document.onclick = log;  // 单击的时候会log
  • 而最后一个就更别说了,这里就相当于是直接把一个函数绑定到window.onclick 上面。也就是说,这段代码相当于 document.onclick = function () {console.log('hello')};

这里搞清楚了,再来看上面的代码,

window.onresize = throttle(function () {
  console.log(1);
});

这里对window绑定了

throttle(function () {
  console.log(1);
});

由上面的分析可知,在代码执行到这里的时候,window.onresize就等于这个函数的运行结果,观察上面的代码,可以知道,这个函数的运行结果就是返回另外一个函数,所以window.onreize就与该函数返回的另外一个函数绑定了。这里就是利用到了闭包。

2015-12-24

  1. 写font的缩写的时候,font-size和family是必须的
  2. collection.where方法返回的是一个数组,所以通过where来获取自己需要的某一个元素的时候,需要在最后加个[0];

2015-12-25

  1. 关于calc
    • 使用这个属性的时候,里面的表达式符号要注意分隔,例如calc(100vw - 100%),运算符号的前后如果不加空格的话,就是一个无效的属性
    • 关于vw,这个值是viewport/100,也就是视口的宽度的百分之一,100vw就是整个窗口的宽度,包含了滚动条,而100%,是当前元素的可用宽度(不含滚动条),所以,在根元素下,calc(100vw - 100%)也就是滚动条的宽度

2015-12-26

  1. 关于Windows下GitHub同步分支失败的解决办法
    • 解决的办法一是可以选择更新libcurl,或者把默认git的默认连接方式由https改为ssh,只需在终端执行以下命令即可:

      git config --global url.ssh://git@github.com/.insteadOf https://github.com/
      
    原文地址

2015-12-27

  1. 操作节点的时候如果需要把一个节点移动到父节点末尾,那么可以直接使用appendChild(),这个方法如果传入一个节点,那么就会把该节点直接放到父节点尾部。。
  2. replaceChild(),两个参数,第一个是要插入的节点,第二个是要替换的节点
  3. HTMLCollection的几种访问方法,假设aLi为对应的HTMLCollection
    • 使用方括号语法或者item()直接访问 aLi[3],aLi.item(3)
    • HTMLCollection的方法:namedItem(),可以通过元素的name来获取
    • 直接使用方括号加名字: aLi['hello']
  4. childElementCount: 返回子元素(不包括文本节点和注释)的个数 firstElementChild: lastElementChild: nextElementSibling: previousElementSibling: 以上属性都不会返回空白文本节点 // IE9以上才支持→_←

2015-12-29

  1. npm安装依赖包出错

     If you are behind a proxy, please make sure that the 'proxy' config is set properly.
     npm err! Error: connect ECONNREFUSED 127.0.0.1:8087
    
    

    具体信息忘记截图了。。。 总之意思就是说代理错误,所以需要更改代理设置,

    npm config set proxy null
    

    然后就能正常运行了。。解决了一个困扰这么久的问题。。心里还是很开心的O(∩_∩)O哈哈~

  2. 关于Switch语句分组的问题,需要在case的后面加:而不是逗号(毕竟不是css),o(╯□╰)o

  3. 关于line-height

    • 没有设置高度的情况下,撑开元素的高度,靠的是行高而不是font-size
    • line boxes的高度取决于它的子元素的最高高度(因此可以给其本身设置一个行高,再在里面添加一个空元素来继承其行高以便撑开)
    • 关于line-height的百分值和小数值, 使用百分比会计算line-height的值,然后以px像素为单位继承下去,而1.5则是先继承1.5这个值,遍历到了该标签再计算去line-height的像素值 也就是说, 使用百分比,会先计算,再继承 使用小数值,会先继承,再计算
    • 使用height会使标签hasLayout, 而使用line-height的话则不会
    • vertical-align的相对值是相对line-height来的
    • vertical-align对块级元素不生效?
  4. 使用“*”通配符的话会大大增加css的渲染,效率低

  5. 监听多个不同的事件时,使用空格分隔

  6. collection也可以使用toJSON(), collection.toJSON(),返回的是collection里面每个model的属性的数组。每个model为一个对象

  7. 关于水平居中,使用绝对定位的话有三种方法

    • 定义left: 50%, 然后margin-left为自身宽度的一半的负值
    • 定义left: 50%, 然后使用transform: translateX(-50%);
    • 定义left和right,使之相等,这样就能把元素撑开并保证左右距离一致了。
  8. chrome控制台里通过$来选取一个元素, 行为和document.querySelector()一致, 可以通过$$来选取一组元素, 行为和document.querySelectorAll一致, 如果在Element里选中了一个元素的话, 通过在控制台里输入$0可以访问选中的这个元素。

  9. 在表单操作当中,取得表单的引用之后,可以直接通过该引用来获取其子元素有id或者name属性的元素

    <form action="" id="testForm">
     <input type="text" name = "testInput" id="hh">
    </form>
    var form = document.getElementById('testForm');

    然后通过form.testInput或者form.hh都可以取到input元素

2015-12-30

  1. 使用MarkDownPreview插件,可以在本地预览.md文件,安装后,在md文件中按ctrl+shift+p调出命令行,输入mdp,选择Preview in browser 即可
  2. 关于按需加载
    • 可以将需要按需加载的内容放在script标签里,然后在需要的时候,将需要展示的盒子的html()设为该标签里的内容,这样子在页面刚刚加载,没有达到触发条件的时候,并不会触发请求
    • 懒加载的实现原理:
      • 生成标签时,用data-src来保存图片地址;
      • 记录的图片data-src都保存到数组里;
      • 对滚动条进行事件绑定,假设绑定的函数为function lazyload(){};
      • 在函数lazyload中,按照下面思路实现:计算图片的Y坐标,并计算可视区域的高度height,当Y小于等于(height+ scrollTop)时,图片的src的值用data-src的来替换,从而来实现图片的按需加载

2015-12-31

  1. DOM元素的classList属性,表示的是当前元素的类名清单。。。
  2. console.log(),里面的内容如果以逗号形式分隔,那么在输出的时候,就会用空格来分隔开来
  3. console.warn(),里面的消息就会以警告的形式出现在控制台里面(感叹号 + 浅黄色背景 )。
  4. console.error(), 会抛出错误,与throw new Error()不同的是,后者会有错误类型Uncaught Error
  5. console.info(),提示类信息,蓝色的小i
  6. console.group(),用于消息分组,console.groupEnd()用来结束分组 需要注意的是,这里只会折叠group到groupEnd的内容,如果分开来写了,就算group的名称相同,也不会合并在一起
  7. console.table(),用于将数据以表格形式呈现
  8. console.time(),console.timeEnd(),用于计算这两个之间执行的代码所用的时间,如
    console.time('用了多久');
    var arr = [];
    for ( var i = 0;i < 1000;i++) {
      arr.push(i);
    }
    console.timeEnd('用了多久'));
    需要注意的是,time和timeEnd里面的参数必须一致,这样才能正确输出。这个方法在做性能测试的时候比较方便
  9. 字符串替换
    • %o 对象替换

      var hello = 123;
      console.log('The number is %o', hello);
      

      这样的话,打印出来的消息里,hello将会替代%o.

    • %d or %i 用于整型替换。如果传入的值是非整数的话,将会强制转换为整数。转换规则和parseInt差不多。使用%o的话则不会转换

    • %s 输出字符串

    • %f 输出为浮点值, 注:原文中%d和%f的描述里有个尚未支持格式化,不懂什么意思

    • %c 使用%c之后,就会对%c之后的内容使用css样式了

      console.log('%chello world','color: red;');

      然后hello world 就会显示为红色

  • 参考内容

  • 关于word-spacing 和letter-space

    • word-spacing 表示的是单词之间的间距(对中文不生效),是单词间距,对中文也是,词间距
    • letter-space 表示的是字符间距,每个单词内字符的间距(中文有效) DEMO

###2016-01-01

  1. JS只有一个主线程,主线程执行完执行栈的任务后去检查异步的任务队列,如果异步事件触发,则将其加到主线程的执行栈。示例如下:
setTimeout(function(){console.log('timeout')},0);
console.log(1);
// 1
// timeout

结果就是1/timeout.

  1. 关于删除节点操作, 不仅仅是删除, 在涉及到集合子项的删除中都是这样
  <input type="button" value="删除" id="delByI++">
  <input type="button" value="删除" id="delByI--">
  <ul>
    <li>节点1</li>
    <li>节点2</li>
    <li>节点3</li>
    <li>节点4</li>
    <li>节点5</li>
    <li>节点6</li>
    <li>节点7</li>
    <li>节点8</li>
    <li>节点9</li>
    <li>节点10</li>
    <li>节点11</li>
    <li>节点12</li>
  </ul>
  var oDel1 = document.getElementById('delByI++');
  var oDel2 = document.getElementById('delByI--');
  var aLi   = document.getElementsByTagName('li');
  oDel1.onclick = function () {
    for (var i = 0; i < aLi.length; i++ ) {
      aLi[i].parentNode.removeChild(aLi[i]);
    }
  };

  oDel2.onclick = function () {
    // 注意这里是aLi.length - 1
    for (i = aLi.length - 1; i >= 0; i-- ) {
      aLi[i].parentNode.removeChild(aLi[i]);
    }
  };

然后在点击第一个按钮的时候,第一次只会删除6个节点(1/2),第二次再点,删除3个,还是(1/2),第三次删掉俩,等点了第四次的时候才能够删完。

为什么呢,因为for循环只有在刚刚开始的时候,才会去初始化i的值,之后每次循环只会判断当前i的值有没有达到停止循环的要求,也就是说,下次循环只会从第二句开始,但是循环每执行一次就会删掉一个节点,这样一来,Li的长度始终都是在变化的,但是i的值却没有发生相应的 变化,比如说,当循环执行到第二次的时候,此时i=1,但是因为删除了一个节点,aLi[i]却等于节点3,也就是跳过了我们期望删除的节点2. 每次循环都这样,所以最后也自然不能按照我们预期进行咯。

解决办法就是从尾部删除。

###2016-01-02

这个不知道该怎么起名。。。

var aLi = document.getElementsByTagName('li');

  for (var i = 0, b; b = aLi[i++]; ) {
    b.onclick = function () {
      console.log(this.innerHTML);
    }
  }

其实这段代码和下面这段代码是一样的效果

for (var i = 0; i < aLi.length; i++) {
    aLi[i].onclick = function () {
      console.log(this.innerHTML);
    };
  }

因为这里访问的this.innerHTML其实是固定的值,当循环开始的时候,就已经为对应的每一个DOM元素绑定了事件了,在后来访问的时候并不涉及到i,所以这种写法并没有什么影响。

至于闭包的话,是这样子的

for (var i = 0; i < aLi.length; i++) {
    aLi[i].onclick = function (i) { //也就是说,这里的i需要在同一个层上,并将其作为参数传入函数内部这样才不会出错
      return function () {
        console.log(i);
      };
    }(i);
  }

这样子的话,当对应元素发生单击事件的时候,打印出来的东西就会是自己期望的值了。

###2016-01-03

  1. 将数组转换为字符串
    var colors = ['red','blue','yellow'];
    
    colors.toString(); // 和colors.join()的效果一样
    colors.join(',');// 给join传递参数的话,那么就会以传递的参数来分隔字符串,没有传参的话,默认为','
    // 把多维数组转化为一维数组
    colors.toString().split(','); // 注意: split 是通过指定标识符把**字符串**切割为数组 // 但是这样子的话,数组项会变为字符串
  • 是一种可以限制插入和删除项的数据结构。LIFO(last-in-first-out),后进先出,也就是最新添加的项最先被移除
  • 方法: push(),pop();
  • push():可以接收任意数量参数并添加到数组末尾,返回修改后数组的长度
  • pop():从数组末尾移除最后一项,返回移除项
  1. 队列
  • 队列数据结构的访问规则是FIFO(first-in-first-out),先进先出。
  • 方法: shift(),push();
  • shift(): 移除数组中的第一个项并返回该项。
  • 添加数组项的方法:unshift(),push(),返回值为添加之后的数组长度
  • 删除数组项的方法:shift(),pop(),返回值是删除项
  1. 数组的方法
  • concat 用于数组合并。不会在原数组上操作。

    var num  = [1,2,3,4,5,6,7];
    var num2 = num.concat(8,9); // [1,2,3,4,5,6,7,8,9]
    var num3 = num.concat([8,9]); // [1,2,3,4,5,6,7,8,9]
    var num3 = num.concat([8,[9]]); // [1,2,3,4,5,6,7,8,[9]]

    concat的一个应用是用来将多维数组转换为一维数组

    var arr = [1, 2, 3, 4, 5, [6, 7, 8, 9, [10, 11, 12]]];
    Array.prototype.concat.apply([], arr); // 然而这个的弊端在于只能转换二维数组, 如果是更高维的话得不到期望值
    // 所以可以用下面这个方法:
    arr.toString().split(',').map((item) => { // 然而如果要是数组里面含有对象的话, 就挂了→_←
      return item - 0;
    });

    两种方法转换数组的性能比较 可以看到, 实际上使用concat的话性能会好很多。只是不一定会转换为一维数组。 事实上, 性能还是相差不大的, 相差比较大的时候, 可能是数据比较大, 也可能是因为数组是多维的, 而concat只能转换二维, 但是String却能全部转换。

    另外一个应用就是可以创建指定长度数组并推入某个值。

    const ary = new Array(31).concat(32); // 得到一个长度为32的数组, 并且数组的最后一项是32

    需要注意的是, 上面不能使用push方法, 因为push返回的是push进去之后的数组长度。当然, 如果是在已有数组上操作的话就另当别论了。

  • slice 基于当前数组中的一个或多个项创建一个新数组。如果有两个参数,则返回的是起始位置到结束位置(但不包括结束位置)的数组。不会在原数组上操作。如果slice的参数中有负数,则用数组长度加上负数来确定相应的位置。

    var ary = function() {
      console.log(typeof arguments.sort);
      var arg = [].slice.call(arguments,0); // 将类数组转化为数组。
      // var arg = Array.from(arguments); // 将类数组转化为数组。
      console.log(typeof arg.sort);
    }(1,2,3,4,5,6,7);
    // undefined
    // function
  • splice

    • 删除: 可以删除任意项。只需指定两个参数:要删除的第一项的位置和要删除的项数(返回值是删除的数组项)。
    • 插入: 插入任意项。 三个参数: 起始位置,0(要删除的项数),要插入的项
    • 替换: 三个参数: 起始位置,要删除的项数和要插入的项数
    • 此方法直接操作的原数组
  • indexOf和lastIndexOf

    • 接受两个参数:要查找的项,和查找的起始位置的索引 array.indexOf(item);
    • 这里来个小小的穿插
    '1,2,3,4,5,6'.indexOf(3);

    那么结果是多少呢??答案是4,因为','也是一个字符啊,:笑cry;

  • 迭代方法

    • 传入的函数接受三个参数:数组项的值,在数组中的位置和数组对象本身(jQuery的each第一个是index)
    • every 对数组中的每一项运行对应函数,如果每一项为true,即返回true
    • filter 对数组中的每一项运行对应函数,返回由返回值为true的项组成的数组
    • forEach 对数组中的每一项运行对应函数,无返回值
    • map 返回每次函数调用的结果组成的数组 需要显式地调用return 来返回
    • some 如果该函数对任一项返回true,则返回true
    • 需要注意的是Array.prototype.forEach和jQuery的each存在几点不同
      • forEach的第一个参数是item, 第二个参数是index, each刚好相反
      • each方法会对传入的参数进行判断, 如果函数的返回值是false则会跳出循环,而forEach则不会。
  • 归并方法

    • 接受两个参数: 一个在每一项上调用的函数和作为归并基础的初始值
    • 调用的函数接受4个参数:前一个值,当前值,项的索引和数组对象
      • 前一个值:通过上一次调用回调函数获得的值。如果向 reduce 方法提供 initialValue,则在首次调用函数时,previousValue 为 initialValue。
    • reduce 从数组的第一项开始
    • reduceRight 从数组的最后一项开始
    • 这个函数返回的任何值都将作为第一个参数自动传给下一项
    • 关于归并函数还是有点不大懂
  • 排序方法

    • sort(),可以传递一个函数作为排序依据,如按照数组项从小到大进行排序:
    var num = [7, 6, 2, 1];
    num.sort(function (a, b){
      return a - b
    });

    如果要逆序的话,将a - b改为b - a即可。这个方法是在原数组上进行操作的。

  • 注意:数组不是基本类型而是引用类型!!!!!!重要的事情说三遍,另外两遍自己脑补

  • for(var i in ary)来遍历数组的话,i是索引索引索引!!!!或者说是数组对象的key值(不会遍历数组的length)

  • 当然。。 用for in来遍历对象的话, 也是key值

  1. 日期对象
  • 月份的表示是基于0的,所以

    var date = new Date(2012,12,12);
    // 转换为时间字符串
    date.toTimeString(); // 得到时间的字符串表示
    date.toDateString(); // 得到时间的日期表示(周几,年, 月, 日)

    所得到的值并不会是2012-12-12而是2013-01-12

    01/20 2016更新

    new Date(2015,12,0)
    // Thu Dec 31 2015 00:00:00 GMT+0800 (中国标准时间)

    也就是说,当天数设为0的时候,获取到的月份与对应的月份是相等的。然后刚好可以通过这个方式来获取一个月份的天数。

  • 实例化日期对象的时候,如果要设置日期,那么传入的日期用逗号分隔,如

    new Date(2012,11,12,12,12,12);

    另外,传入的日期至少要包含两个参数,年和月。如果缺少了1个,那么返回的日期对象将会是从1970开始。未提供天数,则假设天数为1,其他参数默认为0。

  • Date.now()返回调用这个方法时的日期和时间的毫秒数(IE9以上支持,在不支持的浏览器中可以使用+new Date()来代替)ES5提出来的。

  1. 字符串方法
  • charAt;charCodeAt
  • ** 都不会修改字符串本身,而是返回一个修改后的副本 **
  • concat 拼接字符串,然而一般都用+号拼接
  • slice 第一个参数表示字符串开始的位置,第二个参数表示字符串到哪里结束(不包括该字符)
  • substr 第一个参数表示字符串开始的位置,第二个参数表示的是要返回的字符个数
  • substring 第一个参数表示字符串开始的位置,第二个参数表示字符串到哪里结束(不包括该字符)
  • 在给这些方法传递负的参数的情况下
    • slice 将负值加上字符串的长度
    • substr 将第一个负值参数加上字符串长度,第二个负参数转化为0
    • substring 把所有负值都转化为0,然后将较小的值作为开始位置,将较大值作为结束位置
  • indexOf,lastIndexOf
  • trim() 去除空格
  • toLowerCase;toUpperCase; 大小写转换
  • match str.match(pattern); 找到则返回匹配字符串,未找到则返回null
  • search 如果未找到则返回-1
  • replace
  • 关于正则表达式的模式匹配
    • $& 匹配整个模式的子字符串
    • $` 匹配的子字符串之前的子字符串
    • $' 匹配的子字符串之后的子字符串 引号前需要加转义字符
    • $n 匹配的第n个子字符串
    • $nn 匹配的第nn个子字符串,如果没有定义捕获组,则为空字符串
    • 上面指的捕获组,是正则表达式中的括号括起来的部分。如: /(hello)/g,第一个括号就是第一个捕获组,匹配的部分可以用$1表示。
  • split 基于指定的分隔符,将字符串分割成多个子字符串并存进一个数组。可以指定第二个参数来表示数组长度
  • localeCompare 比较两个字符串(貌似没多大用啊)

2016-01-04

  1. 正则相关

    • 匹配双字节字符(包括汉字、全角)

      /[^\x00-\xff]/     // 注意 ^ 这个符号
    • 匹配汉字

      /[\u4e00-\u9fa5]/  //这里没有 ^  这个不会匹配汉字标点符号(其实那个应该算在双字节内)
  2. 关于onunload , 和onbeforeunload事件

    • onunload 书上说主要是用来在卸载页面之前清除引用的,然后我在里面加了事件好像也没什么用,比如alert();这个事件是在文档被完全卸载之后才会触发的。
    • 【3/13注:】其实是有用的, 只不过每次卸载页面要么是关闭窗口, 要么是跳转页面, 控制台就会更新,如果打断点的话就会看到事件处理函数里面的语句是执行了的。
    • onbeforeunload 需要传入事件对象,然后事件对象有个returnValue属性,属性指定的字符串在卸载页面之前会出现在弹窗里。如下
    window.onbeforeunload = function (event) {
      var event = event || window.event;
      var msg   = 'Do you really wanna leave ? '
      event.returnValue = msg;
      return msg;
    };
  3. 博客园里markdown插入代码的话,必须要顶格才能正常显示。 【3/13注:】好久没去博客园了。

2016-01-05

  1. 关于随机数的生成。

    value = Math.floor(Math.random()*可能值的总数 + 第一个可能的值);

    例如: 想要选择一个1-10之间的数,那么可以这样来选择:

    var num = Math.floor(Math.random()*9 + 2);
  2. jQuery的text()方法,只会获取html里的文本内容。

2016-01-06

  1. 使用GitBash时,修改进入之后的默认路径可以右击其图标,然后在起始位置里面输入期望位置。如果重启后操作无效,则看是不是目标位置的最后,有 cd to home字段,如果有的话,就去掉。然后就可以了。

  2. 如果一个字符串为'2014年法律硕士考试提醒', 然后需要匹配2014年之后的内容的话,可以用下面这种方法:

     var str = '2014年法律硕士考试提醒';
     str.match(/2014年(.*)/g);
     var matchResult = RegExp.$1;

    也就是获取捕获组

2016-01-07

  1. 正则表达式的元字符: ( { [ \ ^ $ | ? * + . ] } ),在需要表达他们本身时,需要转义
  2. 直接使用//来定义正则的方式叫做字面量,而使用new RegExp()的方式来定义的话,第一个参数为需要匹配的字符串模式,另一个是标志字符串。字符串中的元字符需要进行双重转义。(1 => 2, 2 => 4)

2016-01-08

  1. 用npm从远程仓库上安装插件失败的话,考虑是不是ssh key的问题,

2016-01-09

  1. 黑体也是可以设置宽度的,设置font-weight:normal,然后就会变成正常宽度了。
  2. 注意啊。。。判断相等是三个或者两个等号!!!!!一个等号是赋值!!!

2016-01-10

  1. 以下代码:

    null ==  undefined // true
    null === undeifned //false

    也就是说null并不严格等于undefined

  2. ArrayLike对象的本质特征是具有length属性

  3. 合并数组

    var arr1 = [1, 2, 3, 4];
    var arr2 = [5, 6];
    var arr3 = [7, 8, 9];
    var arrC = [].concat(arr1, arr2, arr3);

2016-01-12

  1. 微信的内核是webkit,所以用到CSS3的属性的时候需要加-webkit-前缀。→_←微信自带浏览器必须要加前缀
  2. input[type=hidden],隐藏文本域的一个作用是, 可以配合服务端来保存数据。
  3. $_GET[KEY],用于获取URL里面的对应的值
  4. $_SESSION[KEY]使用之前,需要先sesstion_start() // 在定义该SESSTION的时候可以不用,但是在其他页面调用的时候必须先start
  5. 使用require引入文件

2016-01-13

  1. 如果要是在chrome下调试的时候,发现控制台在source等频道下调不出来,只有在console下才能显示的时候,可能是按了esc将console给隐藏了。解决办法是点控制台右上角的三个点,然后选择show console.即可。Of course, you can also press the shortcut esc to show it again.

  2. 绝对定位的时候bottom参照的元素是浏览器的第一屏,当其参照元素在滚动的时候,也会跟着滚动。

  3. textarea禁止拉伸:在css里为其添加rule,resize: none | horizontal | vertical;

  4. 下面的代码:

    var root = (typeof self == 'object' && self.self == self && self) ||
               (typeof global == 'object' && global.global == global && global);

    在默认情况下(没有重写self的引用时),self指向window;self.self指向window,self.self.self指向window,→_← global是nodejs中的全局对象

  5. 定义一个构造器

var Person = function (config) {
  this.name = config.name;
  this.job = config.job;
};
Person.prototype.work = function () {
  return this.name + " is working";
};
  1. 英文的比较好看圆滑的一个字体是'Open Sans'

  2. 访问一个对象的属性时,如果一个该属性不存在,将会返回undefined,如果在这个时候再访问该属性的另外一个属性时,则会直接报错。如:

var obj = {
  team: {
    name: 'hello'
  },
  id: 2,
  member: {
    name: 'Jiangxi'
  }
};
obj.name  // undefined

obj.name.name // Uncaught TypeError: Cannot read property 'name' of undefined

解决办法就是在使用之前先进行判断

obj.name && obj.name.name; // undefined

也就是说,如果要访问一个对象的属性的属性的时候,需要先判断该属性是否存在,如果存在,再进行访问,这样才不会报错

2016-01-14

  1. @keyframe @keyframes,是复数!!! 加前缀是@-webkit-keyframes 而不是-webkit-@keyframes o(╯□╰)o

  2. background-clip: content-box,padding-box,border-box;规定背景的绘制区域,默认为padding-box

  3. rotate(1turn)表示转一个圈

  4. text-transform属性: 控制文字的大小写capitalize,uppercase,lowercase

  5.  Uncaught SyntaxError: Unexpected end of input 通常是因为缺少括号或大括号来结束语句了o(╯□╰)o,怎么就给忘了,不知道错误的原因就注释掉语句看是哪里出了问题,再不行就在其他浏览器下查看报错

  6. 用CSS绘制三角形:

    .arrow{
       width: 0;
       height: 0;  /* 要将高度设为0,不然会显示为梯形 */
       border: 50px solid transparent; /*  三角形侧边 */
       border-top: 0;
       margin: 50px auto;
       border-bottom: 100px solid #f66; /* 设置三角形底边的的长度和三角形的颜色 */
    }
  7. Chrome Cl APIs

  • $ 返回匹配CSS选择器的第一个元素 querySelector
  • $$ 用数组形式返回匹配CSS选择器的元素 querySelectorAll
  • $x(path) $x('//p')返回所有的p元素
  • debug(function) 传递一个函数,当函数调用的时候,会在函数内的第一个可执行语句处断点。取消断点可以用undebug(function)
  • dir(), 同console.dir(), 显示一个DOM元素的可操作列表(可以通过点号访问到的)
  • inspect(object/function) 选中并跳到该元素(或函数)
  • getEventListeners(object), 用于获取注册到object上的事件,对象的键为事件类型,值为注册到该对象上的事件绑定的函数组成的数组。该数组描述了每个事件类型的监听器(也就是该事件绑定的函数),例如可以通过getEventListeners(document).click[0].listener来访问document上click事件绑定的第一个函数
  • keys(object) 返回一个由对象的属性名字组成的数组,对应的有还有 values(object)
  • monitor(function) 当指定的函数调用的时候,将会显示出传入函数的参数
  1. P标签内部只能包含inline标签,如果包含了block标签的话,该block标签将会被提到p的同一个层级。注意,这里指的是默认的block标签,而不是具有display: block的标签 .IE下innerHTML会对错误嵌套报非法错误(未测试)原文地址;
  2. html元素错位,除了考虑嵌套之外,还需要考虑是不是没有补全标签(也该算是嵌套吧)

2016-01-15

  1. display: none会让屏幕阅读机和键盘 Tab 忽略它。因此可以用绝对定位,设置left为一个极大或者极小值,使得元素能够保持在文档流中

  2. 伪元素添加内容的时候一定要添加content属性啊!!!!! 没有content就没有内容就不会显示啊

  3. 当一个元素hover的时候,要改变该元素的伪元素的状态的话,那么:hover 和伪元素之间不能有空格,否则不会生效,如

    div:hover:before{} /* 就是div hover的时候他的伪元素发生对应的变化,注意不能有空格不能有空格!!!*/
  4. 通过transform的scale来控制元素的隐藏和显示,配合transition即可实现动画效果。如下例:

     div{
       display: inline-block;
       position: relative;
     }
     div:before{
       content: '';
       position: absolute;
       left: 0;
       bottom: 0;
       width: 100%;
       height: 2px;
       background: #f65;
       transform: scaleX(0);
       transition: all ease-out .2s;
     }
     div:hover:before{
       transform: scaleX(1);
     }
  5. elem.offsetParent获取的是其父元素?

  6. 注意文件名大小写,Linux上是区分大小写的。

  7. php没有undefined。。。。

2016-01-17

  1. JS不能选中before,after伪元素怎么办????废话。。用其他标签来代替伪元素不得了么。。。。

  2. JS高级程序设计——最佳实践

    • 将事件处理程序和应用逻辑解耦,也就是说涉及到事件的部分,只处理事件,然后将处理的结果传递给应用逻辑
    • 使用常量(用全大写表示),这样将会使代码更易维护
      • 重复值
      • 用户界面字符串
      • URLs
      • 任意可能会更改的值
    • 性能
      • 避免全局查找 将一个语句中多次用到的全局变量存为局部变量 比如, 在一个函数内, 如果有多个地方会用到document的话, 那么可以对document进行缓存, 那么下次再访问document的话话直接在函数的作用域内就能够找到。 从而减小了在作用域链上的寻找时间。

      • 避免使用with语句

  3. \x20表示空格 \f换页符 \t制表符 \r回车符 \n换行符 去除空格的正则表达式 : whitespace = "[\\x20\\t\\r\\n\\f]"

  4. obj.ownerDocument返回节点所属的根元素

2016-01-18

  1. Math.cos() Math.sin()等等涉及到三角函数的方法接受的参数是弧度而不是角度啊啊啊啊啊啊啊!!!!!
  2. const定义一个对象的时候, 可以在之后改变对象的属性,但是不能改变该常量为其他对象。也就是说,可以用const 定义一个对象,然后可以继续修改这个对象的属性方法等. It's also available for Arrays.
  3. 不要为函数参数重新分配值
  4. return可以直接返回一个对象:
function getName() {
  return {
    name: 'Jiangxi',
    age: '22'
  };
}
var person = getName();
person // Object {name: "Jiangxi", age: "22"}
  1. 三元运算符里可以进行函数运算。但是不能直接return 【eslint检测过不了 :笑cry】—— 额。。 不对。。 是根本就不能return , 会报语法错误, Uncaught SyntaxError: Unexpected token return

2016-01-19

  1. $.extend({}, s1, s2, s3..)就是将s1,s2,s3..等合并到第一个参数(一个空对象里),然后再返回这个对象, ES6里的Object.assign()和这个差不多。 然而可恶的IE10对此表示不支持!!!!

  2. 微软雅黑加粗之后看起来简直不像雅黑了!!!!所以如果设置了字体但是感觉不是自己想要的的时候,看看是不是多加了个font-weight吧。

  3. 利用好三元操作符的话可以节省很多代码,真的。如:

     let msg = obj.toString().replace(/,/g,' ').trim().replace(/(\d+)\s*/g, '$1 ').trim().split(' ').join('、');
     msg ? msg = '每月' + msg : '';
     this.$header.text(msg);
     this.$header.prop({ 'title': msg });

    其实这里不仅仅是利用好三元操作符,还有一个就是,如果重复代码比较多的话,可以在前面先进行判断,根据不同的结果,把对应的数据存放到变量里,然后在下面需要的时候就直接使用变量来代替了。

    如果不用三元操作符的话,这里的判断可能会像下面这样:

    if (msg) {
      // 需要注意的是,如果是msg += '每月'的话,那么每月每显示在后面,所以这里没那样写
      msg = '每月' + msg;
    } else {
      msg = '';
    }

    类似这样的操作就可以直接用三元操作符来代替,从而达到节省代码量的目的。

2016-01-20

  1. webpack 在添加loader的时候,对应的loader需要加引号才行,不然会报错。

  2. 在安装依赖的时候用npm install module --save的方式比较快捷吧 。。 当然, 可以同时安装多个包。

    npm install express mongoose jade --save
  3. JSON里的键值应该使用双引号而不是单引号。

  4. webpack的插件是在其配置文件中的plugin中指定, BannerPlugin给输出的文件头添加注释信息

  5. 在插入插件比如 new webpack.BannerPlugin()的时候,需要现在配置文件头部var webpack = require('webpack');

  6. webpack --display-error-details可以打印详细错误信息

  7. 当引入通过 npm 安装的 node.js 模块时,可能出现找不到依赖的错误。Node.js 模块的依赖解析算法很简单,是通过查看模块的每一层父目录中的 node_modules 文件夹来查询依赖的。当出现 Node.js 模块依赖查找失败的时候,可以尝试设置 resolve.fallback 和 resolveLoader.fallback 来解决问题。

  8. dropdown的dropdown-toggle和dropdown-menu应该在同一层目录下。

  9. JS获取当前月的天数:

    new Date(2016,2,0).getDate(); // 使用时把年份换成当前年份,月份换成当前月份(需要注意的是,该是几月就是几月,如2月就是写2)
  10. dropdown的JS方法和添加data-toggle='dropdown'方法只能用一个. 不然的话以两个作为触发条件的话, 最后结果就是打开了又关了。

  11. CSS用important加权重的方法

    line-height: 20px!important; // 这种还是少用吧。。

    注意important的位置和书写方式。

  12. dropdown的水平对齐方式有两种,left和right,因为是相对父元素定位的,所以如果想要实现居中对齐的话,可以通过给父元素添加padding来实现

  13. 获取选中的单选框的索引

    var index;
    [].slice.call(document.forms[0]['h']).map((item, index) => item.checked ? index : null);
  14. 获取年份的时候要使用new Date().getFullYear()才能得到当前的年份,如果使用的是new Date().getYear()的话,将会返回1900到今年的年份数 【3/19注:】居然忘了还有这个API。

  15. 表示小于等于的时候,是不能分开的,必须连在一起。。。 i <= 123;

  16. o(╯□╰)o JS中直接使用%号是求模求模求模, 不是百分比啊。。。。:笑cry

  17. 用了inline-block之后,元素的宽度 * 数量 != 总宽度, 然后给元素加个背景色看看是不是那个间隙搞的鬼!!!只要是涉及到inline-block,然后宽度什么的不对的问题,你懂的。。。

  18. 利用好background-clip的话,可以实现不同的需求。

2016-01-21

  1. 关于取反:

    isMulti = !this.select.start === this.select.end;

    这样写是不对的因为会先计算!this.select.start,然后再判断相等,所以需要先加个括号

    isMulti = !(this.select.start === this.select.end);

    然而何必搞这么麻烦, 这里只是判断start是否等于end

    isMulti = this.select.start !== this.select.end;

    这样才能得到自己想要的结果

  2. jQuery里的nextAll(), prevAll(), nextUtil(), prevUntil()方法

  3. 关于css的hover不一定需要父元素在空间上包裹子元素,只要结构上包裹,就会触发。

2016-01-22

  1. 关于内容撑开滚动条的显示隐藏问题。。。可以给可能会撑开的元素设置overflow-y:auto,让元素的滚动条一直显示,然后利用元素的margin或者padding 把元素的滚动条撑到父元素外面去,再给父元素设置overflow: hidden,然后就能利用障眼法来去掉滚动条了。

  2. 使用setTimeout的异步执行方式可以巧妙地在某些语句之后执行相应语句,尤其是在清类名的时候

2016-01-24

  1. 富文本编辑的两种方式 [据说这是一个大坑, 等以后有能力了真想好好踩踩]
  • iframe
  • contentEditable
  1. document.defaultView.getComputedStyle(),标准推荐的获取样式的方法
  2. 原生JS可以直接通过DOM元素的text属性来访问其文本,不过更好的方法还是通过innerText

2016-01-26

  1. 获取日期,new Date(year, month, date)的时候,如果date为零,那么获取到的将会是上一个月的最后一天,可以通过这个方法来获取一个月的天数。也就是说可以通过
new Date(new Date().getFullYear(), new Date().getMonth() + 1, 0).getDate();
// const date = new Date();
// new Date(date.getFullYear(), date.getMonth() + 1, 0).getDate();

来获取到当月的天数

  1. 如下代码:
Math.random() * 16 | 0; // 0 - 16的随机数 整数

不知道是什么原理。。。总之这里用了这句话之后,就不用再使用Math.floor()来取整了。 卧槽。。好像发现了一个神奇的东西。。。

var random = Math.random() * 16; // 2.7166785709559917
random | 0; // 2
random | 1; // 3

那么是不是就代表 | 后面接0代表向下取整, 后面接1代表向上取整 不对啊。。。 好像是向下取整后,再加上后面的值的来着

random | 3; // 11
random | 5; // 13
random | 199; // 207
random | 200; // 200  // 然而奇怪的是,到了200之后就会变成后面的数值了 // 200 - 207之间

总觉得好神奇的样子。。。

好吧。。。原谅我又看书不仔细了。。或者前看后忘的

  • ~ ,按位非,所得值为操作值的负值减一,如~15值为-16,
  • & , 按位与,两个操作符数,将两个数值的每一位对齐,只有对应位都是1时才返回1
  • | , 按位或,

** 1/27注 ** 这里靠按位或来进行取整并不靠谱,比如

1.5 | 1; // 1
1.566 | 1; // 1
4565.4564 | 1 // 4565

所以还是老老实实的用Math对象的方法来进行取整吧。 。不过这种用来取随机数的话还是可行的。

2016-01-27

  1. 数字toString的时候需要使用括号括起来

    1231231231.toString(16); // Uncaught SyntaxError: Unexpected token ILLEGAL(…)
    (1231231231).toString(16); // "496318ff"

    后面有提到, 因为数值的存储是用的浮点, 所以上面第一句里面的第一个小数点会被认为是小数点而不是点号操作符

  2. 获取样式

info = ('getComputedStyle' in window) && window.getComputedStyle(ele, null) || ele.currentStyle;


### 2016-01-28
1. nodeName.cloneNode(boolean)用于拷贝节点
 ```js
 var oUl = document.getElementsByTagName('ul')[0], cloneUl = oUl.cloneNode(true),
      list = ['10', '11', '12'], temp, i = 0, len = list.length;
  for (; i< len; i++) {
    temp = document.createElement('li');
    temp.innerHTML = list[i];
    cloneUl.appendChild(temp);
  }
  oUl.parentNode.replaceChild(cloneUl, oUl);

虽然直接拼接字符串, 然后一次性的用innerHTML插入会比较好,但是replaceChild还是需要好好理解应用的。 2. 查看页面中DOM元素数量

document.getElementsByTagName('*').length
  1. matchesSelector用来检测dom元素是否匹配某css selector。它为一些高级方法的实现提供了基础支持,比如事件代理,parent, closest等。

    domEle.matches(Selector);
    document.body.matches('body'); // true
  2. JS里不能直接判断两个数组是否相等,用全等或不全等都不行,都会返回false, 可以把数组利用toString转换为字符串再进行比较。

2016-01-29

  1. 关于if语句

    if (!10 % 2) { console.log('123') }  // 不会执行
    if (!(10 % 2)) { console.log(123) }  // 123
    // 因为!运算符的优先级要高于%,所以就会先对10进行取反,得到false, 然后false % 2, 得到的是0,自然就不会执行了。 所以要注意括号的使用
  2. 关于位运算符

    • 判断奇偶
    if (n & 1) { console.log('n是奇数'); } // 如果是奇数,那么值为0
    
    // 原理: 奇数的二进制码的最后一位数肯定是1,而1只有最后一个为1,因此按位&1之后,得到的结果里面肯定只有最后一个数为1了,所以对奇数按位&1之后,得到的结果就肯定是1
    • 按位异或(^) 按位异或是两个数中只有一个1时返回1,其他情况返回0。
  3. jQuery的on方法在绑定的事件之后有个可选的[selector]参数,用于指定特定的后代元素才会触发这个事件

     // 以下代码运行时,只有.container的.left元素才会触发click事件
     $('.container').on('click', '.left', function () {
        console.log('click');
     });
    
     // [selector]后面还有个可选的[data]参数,当使用此参数时,需要给绑定的函数传递事件对象,然后访问[data]时,通过事件对象的data属性来进行访问
     $('.container').on('click', '.left',{name: 'Jiangxi'},  function (e) {
        console.log('click' + e.data.name);
     });
  4. jQuery自定义事件

    • 首先给元素绑定一个事件,设置一个函数

    • 然后触发

    • 原生:

      var event = document.createEvent('CustomEvent');
      event.initCustomEvent('sayHello', true, false, 'hello world');
      ...
      ele.dispatchEvent(event);
  5. npm uninstall module --save-dev的时候,如果dependencies里面也有这个包的话,那么卸载的时候也会把里面的都给卸载掉

2016-01-30

  1. 关于webpack加载babel-loader的一些注意事项

    • 需要安装的依赖包: babel && babel-core && babel-preset-es2015 && babel-loader && babel-plugin-add-module-exports

    • 需要注意的是,需要在当前项目根目录下建立一个.babelrc文件,然后里面内容如下:

       {
         "presets": [
           "es2015"
         ],
         "plugins": [
           "add-module-exports"
         ]
       }
    • babel-plugin-add-module-exports是为了添加ES6的import 和 export功能

  2. webpack命令

    • webpack 最基本的启动webpack的方法
    • webpack -w 监听文件变更,并实时更新
    • webpack -p 对打包后的文件进行压缩
    • webpack -d 提供sourcemap, 方便调试
  3. 【CSS-MDN学习】

    • text-decoration-color: 用于更改文字修饰线条的颜色,默认值为currentColor目前只有FF和safari支持这个属性
    • text-overflow: 可以取字符串,也可以取两个值。。。当然,只有FF支持这个属性
  4. 来点英语吧

    • era 时代,纪元
    • dynamic 动态的
  5. 注意!!!!webpack.config.js里面,loader是module之下的一个对象。。。别落下了。。

  6. 关于数组的reduce方法

  7. 箭头函数内部的this为函数定义处的上下文的this, 箭头函数对上下文的绑定是强制性的,无法通过apply或者call来改变相应的值。 因此不要随意在顶层作用域使用箭头函数以防出错

  8. 因为调用babel转码ES6时,用的是严格模式,在严格模式下,顶层作用域中的this不是指向window的,而是undefined

  9. 关于class的static静态方法。

  10. import { } from '', 表示局部引入

  11. 覆盖整个模块儿的暴露对象,需要在export后面加上default export defalut

  12. promise

    • 要为一个函数赋予 Promise 的能力,先要创建一个 Promise 对象,并将其作为函数值返回
    • 要求创建一个函数并且带有resolve和reject参数
    • 如果函数内部需要用到this,那么就需要使用this的别名,或者使用箭头函数

2016-02-01

  1. 设置font-size: 0来消除inline-block元素中间的间隙在Safari下不可行。。。所以还是使用浮动吧 。。

  2. 关于backgound-clip在IE下表现不对的问题。。 可以通过border来搞定。DEMO, padding配合background-clip和border可以做出不少有意思的东西[好吧, 其实那些只需要border就行了]

  3. 对于input text元素尽量使用padding来实现居中啊。。。

2016-02-02

  1. ellipse----椭圆 individual ---- 个人的 denote --- 指示, 指出

  2. 关于border-radius

    • 当为一个值的时候, 表示四个角一样
    • 为两个值的时候, 第一个值表示左上角和对角, 第二个值表示右上角和对角
    • 为三个值的时候,第二个值表示右上和左下
    • 使用'/'来分隔的时候, 可以定义不同方向的值。 '/'之前表示水平方向,之后表示垂直方向
    • 当border-collapse为collapse的时候, border-radius不能作用于表格元素
  3. 查找一个元素在数组中的索引:

    var arr = ['test1', 'test2', 'test3', 'test4'];
    arr.indexOf('test1'); // 0

    要注意的是, 是arr.indexOf()....

  4. position: relative对表格元素无效。

  5. 清除IE下INPUT元素的叉叉, ::-ms-clear{display:none} 清除密码查看: -ms-reveal{display:none}.

  6. #233看起来好像也确实不错哈。

  7. 关于bind:

    var name = 'Jason';
    var obj = {
      name: 'Daisy',
      sayName: function (name) {
        console.log(name);
      },
      sayHello: function () {
        console.log('hello ' + this.name);
      }
    };
    
    obj.sayHello(); // hello Daisy
    obj.sayHello.bind(this)(); // hello Jason
    obj.sayName(obj.name); // Daisy
    obj.sayName.bind(this, 'Jason'); // Jason

    以上有两个需要注意的地方,

    • 一个是对函数使用bind的时候,需要对函数本身而不是函数的执行结果进行绑定,也就是说,绑定的时候应该是obj.sayHello.bind(this)()而不是obj.sayHello().bind(this)(). 当然了,有了ES6的箭头函数之后, 就没必要这么麻烦了。 需要注意的是,对函数使用了bind()之后只是绑定了函数执行环境的this,还要加上括号才表示执行函数。
    • 另外一个就是,传递参数的时候,可以在bind()的第二个参数之后传递, 多个参数之间直接用逗号分隔
    • 当然,也可以只给bind()传递this,然后在执行函数的括号里面传递具体参数

2016-02-03

  1. 元素的位置通过指定与其最近的position属性非static的元素来确定。
  2. position: fixed的元素的宽度使用百分比的话, 其宽度是相对窗口来的而不是相对其父元素来
  3. 对于使用transform来进行变换的元素, 可以利用left,top, margin-left, margin-top(如果可以用的话)来进行微调。
  4. 通过jQuery获取元素,得到的是一个类数组对象
  5. ::selection永远只能用两个冒号开始, 毕竟伪元素
  6. 使用变量来代替对象属性的话可以避免对象引用发生变化时可能出现的错误。
  7. font的简写中, style | variant | weight在font-size的前面

2016-02-16

  1. 闭包相关:

     var hello = (function () {
       var hello;
       console.log(hello);
       return function () {
         if (hello) {
           console.log('preHello is ' + hello);
         } else {
           hello = 'hello';
           console.log(hello)
         }
       }
     })();
     hello(); // hello
     hello(); // preHello is hello
  2. 多个变量同时声明:

(function () { var a = b = c =1; // 只声明了变量a console.log(a, b, c); // 1 1 1 })(); a // Uncaught ReferenceError: a is not defined(…) b // 1 c // 1

也就是说,通过以上的方式来声明变量的话, b和c成了全局变量,但是a依然是局部变量

3. 关于```unload```事件,应该加在window上,这样在每次刷新或者卸载页面的时候就会触发该事件。
4. 关于`Generator`
```js
 function* testGenerator() {
   yield 's1';
   yield 's2';
   return 'end';
 }
 var test = testGenerator();
 test.next(); // Object {value: "s1", done: false}
  • 在调用generator函数之后,该函数并不执行, 返回的只是一个指向内部状态的指针对象
  • 通过调用遍历器对象的next()方法,来使得指针移向下一个状态
  • value 为 当前值, done表示遍历未完成
  • ES6没有规定*号需要写在哪个位置。。。
  • yield语句如果用在表达式中, 则需要加括号,在用作函数参数或者赋值表达式右边时则不用
  • yield语句默认是没有返回值的, 如果需要有返回值,那么需要在调用next方法的时候传递参数true, 得到的返回值为上一个yield值
  1. 当需要获取当前毫秒的时候,可以使用new Date().getTime(), 但是直接使用+ new Date()却更为简便

2016-02-17

  1. 关于Promise

     let promise2 = new Promise(function(resolve, reject) {
       console.log('Promise');
       resolve(); // 将promise的状态由pending转化为resolve
       reject();
     });
    
     promise2.then(function() {
       console.log('Resolved.');
     }, function() {
       console.log('Rejected');
     });
    
     console.log('Hi!');
     // Promise
     // Hi!
     // Resolved.
    
     // 异步加载图片
     function loadImageAsync(url) {
       return new Promise((resolve, reject) => {
         const image = new Image();
         image.onload = () => {
           resolve(image);
         };
         image.onerror = () => {
           reject(new Error(`Could not read image at ${url}`));
         };
         image.src = url;
       })
     }
    
     const t = loadImageAsync('https://www.baidu.com/img/bd_logo1.png');
    • Promise的then方法返回的是另外一个新的实例
    var t1 = t.then((value, t1, t2) => { return 'Daisy' })
     .then((value) => {
       console.log(`the prev value is ${value}`);
       return 'Jason';
     }).then((value) => {
       throw new Error('nonono');
       return 'error';
     }).catch((error) => {
       console.log(error);
       return 'Catch';
     });
    
     var t3 = new Promise((resolve, reject) => {
       resolve('JASON');
     }).then((e) => {
       console.log(`The prev value is ${e}`);
       return 'Daisy';
     }).then((e) => {
       console.log(`The prev value is ${e}`);
       const err = new Error('invalid value');
       throw err;
     }).catch((e) => {
       console.info(e);
     });
     // The prev value is JASON
     // The prev value is Daisy
     // Error: invalid value(…)
    
     // 通过这种方法可以直接生成实例
     var i = Promise.resolve('Jason');
     var j = Promise.reject('Jason');  // 会抛出错误
  2. Object.assign用于一次性的向对象添加多个属性或方法

     var obj = {}
     Object.assign(obj, {
       name: 'Jason',
       sayName () {
         console.log(this.name);
       }
     });
     console.log(obj); // Object {name: "Jason"}
  3. class

    • constructor方法: 在使用new操作符生成实例的时候,会自动调用此方法
    • class内部定义的方法默认保存到其原型对象上
    • class不存在变量声明提升
    • 类之间的继承是通过extends来实现的。
     class Person {
       constructor (name) {
         this.name = name;
       }
       sayName () {
         return this.name
       }
     }
     class PersonDetail extends Person {
       constructor (name, age) {
         // super指代父类的实例, 必须要调用super()之后才能够使用this,不然会报错
         super(name); // 调用父类的constructor方法。 这里必须要这句话。并且需要传入父类的constructor调用时所需的参数
         this.age = age;
       }
     }
    • 所有在类中定义的方法都会被实例继承, 如果在方法前加上static, 则该方法不会被实例继承 , 而是直接通过类来调用,也就是‘静态方法’, 父类的静态方法可以被子类继承
    • new.target用于确定调用函数时有没有使用new操作符,如果没使用,那么值为undefined。class内部调用new.target, 则指向该class,如果在继承的时候使用,将会指向子类。 class 构造器必须要使用new操作符
     function Person2(name) {
       if (new.target !== undefined) {
         this.name = name;
       } else {
         throw new Error('必须使用new生成实例');
       }
     }
     var p2 = Person2('Jason');
     // Uncaught Error: 必须使用new生成实例(…)
  4. 箭头函数

    • 下面的f表示函数名, (a,b)表示函数参数, => a,a表示函数返回值。
    var f = (a, b) => a;
    • 如果函数有多个语句的话, 用花括号包围
    var f = (a, b) => { console.log(a);console.log(b) }
    • 如果函数的返回值为一个对象, 那么需要用圆括号将该对象包围
     var f = (a, b) => ({ id: a, name: b });
    • 箭头函数不能使用new操作符, 不可以使用arguments, 不可以使用yield命令,所以不能用于Generator函数
    • 函数中的this指向定义时所在对象而不是使用时的对象
  5. Object.prototype.hasOwnProperty()参数是个字符串啊字符串o(╯□╰)o MDN-Object

  6. 关于Object.prototype的简写为({}), 如({}).hasOwnProperty(), 如果不用圆括号包裹花括号的话, 就会报错。。。 因为花括号默认为块级代码。

  7. prototype.isPrototypeOf(object)检测一个对象是否在另一个对象的原型链上。

    function A() {}
    function B() {}
    
    A.prototype.isPrototypeOf(B); // false 这里应该为一个对象, 也就是B的原型对象
    B.prototype = new A(); // B的原型对象指向A的实例, 也就是B继承了A。 那么A的原型对象就在B的原型对象的原型链上。
    A.prototype.isPrototypeOf(B.prototype); // true // A的原型对象在B的原型链上
    
    var a = new A();
    a instanceof A; // instanceof 的左边是一个对象,右边是一个(构造)函数。

    instanceof不同, isPrototypeOf用于两个对象之间, 而instanceof用于一个对象和一个构造函数之间

  8. obj.propertyIsEnumerable()

    • 返回一个布尔值, 表示指定的属性名是否是当前对象的可枚举属性
    class Person {
      constructor (name) {
        this.name = name;
      }
      sayName () {}
    }
    var person = new Person('Jason');       // undefined
    person.propertyIsEnumerable('name');    // true
    person.propertyIsEnumerable('sayName'); // false
    • 可枚举属性是可以通过for...in..遍历到的
  9. 代码:

    var obj = {
       foo: 1,
       get bar() {
           return 2;
       }
    };
    obj.bar; // 2
    
    var to = Object(param); // 这里param是什么类型, 那么to便是什么类型
    // 如, var to = Object({ id: 123 }); 那么to为 { id: 123 }
    
    Object.keys(obj); // 得到的是由obj的键名组成的一个数组
  10. Object.getOwnPropertyDescriptor(obj, prop)

  • 获取对象obj的prop属性的属性描述符, 如果obj不具有prop属性, 那么返回值为undefined
 var obj = { id: 12 };
 Object.getOwnPropertyDescriptor(obj, 'id'); // Object { value: 12, writable: true, enumerable: true, configurable: true }

2016-02-23

  1. 关于拖拽
    • mousedown事件加在拖拽元素上
    • mouseover, mouseup事件在mousedown事件内部绑定
    • mouseover, mouseup事件需要绑定在document对象上
    • 真的。。 肺腑之言

2016-02-18

  1. 关于Object.defineProperty()

    var obj = { name: 'one' }, obj2 = {};
     Object.defineProperty(obj, 'name', {
       value: 'One'
     });
     Object.defineProperty(obj2, 'name',{
       value: 'Two'
     });
     Object.getOwnPropertyDescriptor(obj, 'name'); // Object {value: "One", writable: true, enumerable: true, configurable: true}
     Object.getOwnPropertyDescriptor(obj2, 'name'); // Object {value: "Two", writable: false, enumerable: false, configurable: false}

    也就是说通过``Object.defineProperty```来定义一个尚未存在于对象中的属性的时候, 该属性的未定义特性将会为false, 如果该属性已存在与对象之中, 那么其未定义特性将为true;

  2. chrome快捷键

  • F12 || ctrl + shift + I或者command + option + i --- 打开开发者工具
  • ctrl + shift + c --- 检查元素
  • ctrl + shift + j --- 打开开发者工具并使控制台获取焦点
  1. document.documentModeIE的特性,通过这个可以判断是否是IE。
  • documentMode的值表示当前IE浏览器在哪个文档模式下工作---IE11 -> 11, IE8 -> 8...
  1. 关于把一个对象赋给另一个对象

     // 简单的对象赋值
     var obj = { name: 'Jason' }, obj2 = obj;
     obj2.age = 22;
     obj // Object {name: "Jason", age: 22}
     obj2 // Object {name: "Jason", age: 22}
     // 也就是说,当obj2发生变化的时候,obj也发生了变化, 这与对象按引用传递的概念是相吻合的
  2. Object.is(arg1, arg2), 用于比较arg1和arg2是否相等。 与===不同的是, ===在判断+0 === -0的时候会返回true, 在判断NaN === NaN的时候会返回false, 而通过Object.is()来判断的时候就刚好相反。

  3. 关于set

var o = Object.create({}, {
  foo: {
    writable: true,
    configurable: true,
    value: 'hello'
  },
  bar: {
    configurable: false,
    get: function (){ return 10; },
    set: function(value){console.log(value)} // 通过o.bar = val来访问
  }
});

也就是说,访问器属性里面, 直接通过o.bar来访问的话, 会调用get函数, 如果对o.bar赋值的话, 会调用set函数, 需要注意的是, 用o.bar(val)来设置的话会报错啊/(ㄒoㄒ)/~~

  1. 关于Object.create()
var o = Object.create({}, {
  p: {
    value: 43
  }
});
Object.getOwnPropertyDescriptor(o, 'p');
// Object {value: 43, writable: false, enumerable: false, configurable: false}

也就是说, 通过Object.create(proto, [ propertiesObject ])来创建对象时, 其省略的属性特性默认值为false. propertiesObject是一个对象, 属性名为新创建对象的属性名称, 值为属性特性描述符。

var o = {
  name: 'Daisy',
  age: 22
};
var o2 = Object.create(o, {
  husband: {
    value: 'Jason'
  }
});

o2; // Object {husband: "Jason"};
o2.__proto__; // Object {name: "Daisy", age: 22};

// 通过Object生成的对象, 具有一个原始值PrimitiveValue, 可以直接操作, 如a + 5之类
var a = Object(123);
a; // Number {[[PrimitiveValue]]: 123} Primitive: 原始的
var b = 123;
b; // 123;

也就是说, 通过Object.create(proto)创建得到的新对象的__proto__属性即为proto对象

Polyfill待看 9. 关于Object.preventExtensitions, Object.freeze, Object.seal

  • Object.preventExtensitions: 阻止对对象添加属性, 但是可以操作现有属性
  • Object.freeze: 阻止添加新的属性和操作已有属性, 也就是说该对象将会处于不可变状态
  • Object.seal : 不能添加属性和删除属性, 但是可以修改现有属性。

2016-02-19

  1. setTimeoutsetInterval未指定时间的时候, 默认的时间会受浏览器的影响。chrome默认为0

  2. 清除定时器是使用clearInterval(timerId)或者clearTimeout(timerId), 而不是直接将timerId = null, 真的是笑cry. demo

  3. 将多维数组转化为一维数组:

    const arr = [1, 2, 3, 4, [5, 6, 7, 8, 9]];
    let   arr2 = arr.toString().split(',').map(item => item - 0);
    arr2; // Array [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
    
    // 也可以像下面这样
    [].concat.apply([], arr); // 这里不能使用call

2016-02-24

  1. 变量声明提升和函数声明提升

    console.log(x); // function
    var x = '123';
    function x () {}
    console.log(y); // function
    function y () {}
    var y = '123';

    也就是说, 变量声明提升优先于函数声明提升。这样来看吧。 。

    // 首先进行变量声明提升,此时 var y = undefined, 声明了y但是没有赋值
    // 然后进行函数声明提升,把函数赋给了y
    console.log(y);
    function y () {}
    var y = '123';
  2. 使用:empty选择器来实现contentEditabel元素的placeholder效果:

     <div contenteditable = 'true'></div>
    div[contenteditable = 'true']{
      width: 400px;
      padding: 10px;
      line-height: 28px;
      min-height: 400px;
      border: 1px solid rgba(0, 0, 0, .3);
    }
    div[contenteditable = 'true']:empty:before{
      content: '请输入内容';
    }

    实现contentEditable元素的placeholder效果DEMO

  3. CSS也要注意目录分层

  4. 隐藏滚动条效果:

    <div class='list'>
     <div class="wrap">
       <ul>
    
       </ul>
     </div>
```
.list{
  width: 140px;
  overflow: hidden;
  height: 600px;
  outline: 1px solid #f66;
}
.wrap{
  width: 157px; /* 包裹元素要比外层元素多17个像素, 17为滚动条的宽度 */
  height: 600px;
  overflow-x: hidden;
  overflow-y: scroll; /* 让滚动条一直显示出来, 并将其挤出内容区即可达到隐藏滚动条效果*/
}
ul{
  width: 157px;
}
  1. 使用CSS计数器

    • counter-reset: countername, startValue 后面跟一个计数器的名字和起始值, 如counter-reset: list 2表示初始化list计数器的值为2, 默认为0.
    • counter-increment: countername[,step] 指定增加的计数器和步进, 如: counter-increment: list 5, 则表示计数器list将会从5开始并以5为步进计数5, 10, 15.。。
    • content: ' ' counter(list) 调用计数器
    • 计数器需要配合:before, :after伪元素的content属性来使用 计数器&&隐藏滚动条DEMO 多个计数器目录结构
    • Math.trunc() 用于去除一个数的小数部分, 参数可以为字符串或者数字,或者布尔值
    • Math.cbrt() 用于计算一个数的立方根
  2. Array.from()可以把一个类数组对象转化为数组。可以接受第二个参数, 用来处理传入的数据并返回。

    Array.from(arrLike, (item, index, ary) => {
      console.log(item, index, ary);
      return item + 5;
    });
    // 1 0 undefined
    // 2 1 undefined
    // 3 2 undefined
    // Array [ 6, 7, 8 ]
  3. 箭头函数不能用作构造函数。

  4. 如下代码: 关于Object的简写:

var name = 'Jason', age = 22, obj = { name, age };
obj; // Object { name: "Jason", age: 22 }
  1. 关于属性赋值器
 var person = {
   _name: 'Jason',// 注意这里要加下划线, 不然会出现无限递归调用从而报错
   get name () {
     return this._name;
   },
   set name (value) {
     this._name = value;
   }

 }
 person._name
 // "Jason"
 person.name
 // "Jason"
  1. 属性名的简洁写法的情况下, 属性名始终是字符串:
var obj = {
  class () {

  }
};

定义属性名的时候可以用[], 里面可以用变量或者表达式或者字符串

var relation = 'husban', name = 'Jason', obj = {
  [relation]: name
};
obj
// Object { husban: "Jason" }
**属性名与简洁写法不能同时用, 会报错**
  1. Proxy
var obj = new Proxy({}, {
  get (target, key, receiver) {
    console.log(target, key , receiver);
  },
  set (target, key, value, receiver) {
    console.log(target, key , value, receiver)
   }

});
obj.name = 'Jason'
// Object {  } name Jason Object {  }
// "Jason"

2016-03-01

  1. 注意inline-block元素默认对齐方式为基线对齐
  2. return后面不能直接跟throw new Error()
  3. forEachmap在遍历一个数组时, 将会自动忽略数组的undefined项, 并且不执行该次遍历 s

2016-03-03

  1. 好像绝对定位的元素可以不受滚动条影响? 这个可以好好 研究下。 然而并不是。。 只是特定场景下出现的效果而已。

2016-03-04

  1. 单例模式

    var Time = (function () {
      var time;
      return function () {
        if (!time) time = + new Date();
        return time;
      };
    })();
    Time(); // 1457024261571
    Time(); // 1457024261571
    Time(); // 1457024261571
    Time(); // 1457024261571
    Time
    // function () {
    //   if (!time) time = + new Date();
    //   return time;
    // }

    也就是说下次执行Time()的时候执行的只是最开始赋值时得到的那个函数, 由于闭包, time一 直常驻于内存中, 所以通过闭包的返回值来访问该值的话一直能够访问到, 从而获取到的是最开始得到的值。 。

2016-03-05

  1. module.exports = moduleNameexports.moduleName = moduleName的区别在于通过前者导出的是可以直接访问到的,而后者导出去的require得到的是一个对象, 需要再访问这个对象的对应属性才能拿到对应的模块儿

2016-03-07

  1. concat不是在原数组上操作不是在原数组上操作!!!
  2. JS里的数字是用浮点数来保存的。 所以。。
5.52.toFixed(2); // '5.52'
5.toFixed(2);   // Uncaught SyntaxError: Unexpected token ILLEGAL(…)
5..toFixed(2);  // "5.00"
(5).toFixed(2); // "5.00"

因为数字后面默认会有个小数点。。 所以使用5.toFixed()的时候, 那个点号表示的是小数点而不是操作符 3. 关于函数

var test = function te () {
  console.log(test === te); // true 表示在这里两者都可以访问到。 并且是等价的。
};
test; // function te...
te; // te未定义
  1. 关于return, continue, break
 var obj = {
   name : 'Jason',
   age: 22,
   gender: 'male'
 };
 for (const key in obj) {
   console.log('start');
   if (key === 'name') continue; // 跳出本次循环, 继续下次循环
   console.log('end')
 }
 for (const key in obj) {
   console.log('start');
   if (key === 'name') break; // 跳出所有循环, 执行循环外的语句
   console.log('end')
 }

return 用于函数中返回一个值。 在非函数的环境中使用的话会报错。 5. GIT命令

  • ls -ah可以用于查看隐藏文件(夹)(其实这个并不是git命令而是Unix命令)

  • git add filename 把文件添加到仓库 -- 暂存区

  • git add . 即可一次添加所有更改文件

  • git add --all 添加所有,有时候如果要是有删除记录的话, 那么git add .可能并不能够顺利添加, 此时就需要使用git add --all命令

  • git commit -m 'msg' 把文件提交到仓库 -- 将暂存区的所有内容提交到当前分支

  • git status 可以查看当前仓库的状态

  • git diff查看改变的地方 (difference) 用于在add之前查看?

  • git diff [<options>] [<commit> [<commit>]] [--] [<path>...], 如git diff HEAD -- readme.md

  • git diff <srcBranch> <targetBranch>

  • git log可以查看提交记录, git log --pretty=online美化提交记录

  • HEAD表示当前版本, 上一个版本是HEAD^, 上上个版本是HEAD^^, 当有100个版本的时候则写成HEAD~100

  • git reset --hard HEAD表示回退到上一个版本

  • git reset --hard后面不跟版本号的话会回退到最近提交的版本上。 如果只add了但是没有commit,那么add的内容就会丢失

  • git reflog用于查看命令历史

  • ``cat filename```即可查看文件

  • ``git checkout -- readme.md ```可以放弃工作区内对指定文件的修改。。 注意→_←: 中间的两根中划线前后都有空格

  • git push -u orgin master把本地分支master 推送到远程。 由于远程库是空的,所以第一次推送的时候加上-u参数

  • git remote add origin git@github.com:374632897/git.git 关联远程仓库

  • git clone git@github.com:374632897/cropper 即可克隆远程仓库

  • git checkout -b test表示创建test分支并切换到该分支, 相当于git branch test, git checkout dev

  • git merge用于合并指定分支到当前分支。

  • git branch -d branchname删除指定分支 不能删除当前分支

  • git log --graph可以查看分支合并图

  • 通常情况下, 在合并分支的时候git会使用Fast forward模式,这种模式下删除分支后会丢失掉分支信息。

  • git merge --no-ff -m 'some msg' branchname 即可使用非Fast forward模式来合并分支。 因为这种合并方式会产生新的commit所以需要加上-m参数

  • *************************************************************************

  • git stash 命令需要看一下

  • git stash可以将当前内容存储起来, 以后再进行恢复

  • git stash apply可以将当前stash恢复, 但是并不会删除stash里的内容, 需要调用git stash drop来删除。

  • git stash pop可以恢复当前stash, 并将该stash删除

  • git stash list可以用来查看当前stash列表

  • git branch -D branchname用来强行删除一个分支, 用于分支有更改但是尚未合并的情况

  • git remote用于查看远程分支的信 息

  • git remote -v查看更多的远程分支信息 如果没有推送权限则看不到push的信息

    origin  ssh://git@github.com/374632897/git.git (fetch)
    origin  ssh://git@github.com/374632897/git.git (push)
  • git pull可以把远程的更新抓取下来

  • git tag <name> 用于新建一个标签

  • git tag -a <tagname> -m 'some msgs'用于指定标签信息

  • git tag可以查看所有标签

  • git push origin <tagname> 推送一个本地标签

  • git push origin --tags可以推送全部未推送过的本地标签

  • git tag -d <tagname> 可以删除一个本地标签

  • git push origin :refs/tags/<tagname>可以删除一个远程标签

  • git config --global color.ui true让git显示颜色

2016-03-09

  1. mongoosemodel
var PersonModel = mongoose.model('modelname', PersonSchema, 'CollectionName');

第三个参数才是真正的集合名(表名), 至于第一个参数随便怎么命名都行的。。 o(╯□╰)o 这个问题困扰自己这么久,结果一不小心看到了答案。。原来还是自己没有认真看API。

  1. 要删除数组中的指定值的项, 其实直接使用filter就挺好的了→_←

  2. 关于Notification

    • Notification.permission可以获取桌面通知显示权限, default为拒绝, denied表示用户不想要通知,granted表示用户同意接受通知。
    • Notification.requestPermission()执行此方法即可向用户请求权限
    • 要生成一个桌面通知即可通过new Notification(some msgs)来实现.
  3. 关于calc()函数

    • calc(100% - 90px)表示宽度为当前元素的父元素可用宽度的100%减去90像素得到的宽度。这个应用场景还是比较宽泛的。

2016-03-11

  1. 关于自增自减运算符,

    (function () {
       var i = 0;
       console.log(i++); // 0 // 先执行再增加
       console.log(i);   // 1
    })();
    (function () {
       var i = 0;
       console.log(++i); // 1 // 也就是说前置自增运算符会先计算再执行
       console.log(i);   // 1
    })();

    后置递增(递减)优先级要高于前置递增(递减)一位。优先级这种事情完全没必要记,不过常用的还是需要记一下的, 其他的则应该尽量使用大括号来标识, 不然就算你会懂,别人也不一定会懂。

  2. void运算符表示表达式放弃返回值。

2016-03-12

  1. 一个模块中的JS代码仅在模块第一次被使用时执行一次,并在执行过程中初始化模块的导出对象。之后,缓存起来的导出对象被重复利用。
// counter.js
'use strict'
let i = 0;
module.exports = () => {
  return ++i;
}

// test.js
const count1 = require('./counter.js');
const count2 = require('./counter.js');

console.log(count1 === count2); // true  也就是说实际上通过count2访问到的就是count1这个函数而不是另外又加载的函数
console.log(count1()); // 1
console.log(count2()); // 2
console.log(count2()); // 3
console.log(count1()); // 4
  1. 关于NODE_PATH --- 原来这个是在环境变量里定义的→_→ 不是在程序里
  2. 如果要引入目录下的index.js那么可以直接使用该目录的名字..
  3. node /path中的path其实是针对该磁盘目录的绝对路径.
  4. process.argv[0]表示nodejs执行程序的路径

2016-03-14

  1. 对于含有标签的内容,想获取纯文本的哈, 如果要是觉得用正则来替换会比较麻烦的话, 可以使用jQuery的text()方法。

    $(`<p>${title}</p>`).text() // 这样就能够获取该字符串内的纯文本了。
  2. 直接用赋值方式将一个数组赋给另一个数组的话, 这两个数组实际上还是相互影响的, 也就是说他们是指向的同一个引用。 要想实现复制行为,可以用[].concat()

  3. Parsing error: Duplicate data property in object literal not allowed in strict mode指的是在一个对象下面定义了重复的键值 →_←

  4. li:nth-child(2)表示选中li父元素的第二个且为li的子元素,

  5. p标签内不能有默认为block的标签

###2016-03-15

  1. chrome快捷键
  • 用于选择DOM元素, 折叠、展开元素
  • ENTER 编辑DOM元素属性
  • H隐藏DOM元素
  1. 关于web worker:
 // worker.js
var getData = function () {
  const xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function (res) { // 注意这里的onreadystatechange是全部小写的啊
    if (xhr.readyState === 4 && xhr.status === 200) {
      try{
        self.postMessage(xhr.responseText); // 注意: 获取响应是通过xhr.responseText来获取。
      } catch (e) {}
    }
  };
};
xhr.open('get', 'http://localhost:99/task/kanbanArchive/list');
xhr.send();
getData();

// index.js
const worker = new Worker('./worker.js');
worker.onmessage = (res) => {
  console.info('worker has get sth, ', res);
};
  • web worker不能访问主进程中的全局变量
  • web worker需要遵守同源策略
  • new Worker()的时候传递的参数为一个指向需要执行的文件的url
  1. timeStamp时间戳

  2. 关于Backbone.Relational, 如果要对关联的collection进行reset需要在绑定collectionrelationmodel里进行操作。如果在collection里面操作的话, 最后会在relation里面再度重置, 从而无法达到期望效果。

2016-03-16

  1. webpack的一个问题, 直接复制粘贴文件或者文件夹的方式来更改文件的话, 那么webpack编译后的文件依然是原来的文件。 不知道是配置的问题还是他本身的问题。

  2. 通过检测滚动条的距离来实现按需加载

    • 通过getBoundingClientRect()
    • 获取容器元素的getBoundingClientRect()bottom的值。
    • 获取容器最后一个元素的getBoundingClientRect()bottom的值。
    • 前者减后者, 当所得值大于某个负值的时候发送请求加载内容。
    • 这只是针对自己所需业务场景做的总结→_←

2016-03-17

  1. 连续按两次shift即可查找工程内的文件或函数, ctrl + shift + n
  2. F3查找下一个, shift + f3查找上一个
  3. ctrl + r文件内代码替换, ctrl + shift + r指定目录内代码批量替换
  4. `import {} from 'path'`` 可以将路径里的对象一次性地获取到
  5. `export default {}``可以将当前模块儿的变量以对象属性的方式导出

2016-03-18

  1. 调用表单的reset方法, 可以重置表单

  2. 直接调用localStorage.attr = value即可添加属性值到本地存储→_←

  3. 页面可见性API

    • document.hidden {boolean} 表示当前页面是可见还是不可见
    • document.visibilityState 返回当前页面的可见状态
    • prerender
    • preview
  4. chrome

    • source面板下, 如果代码区左下角有{}的话, 点击就可以格式化代码, 在针对压缩后的代码的时候尤其适用
    • 在断点调试的时候, 如果一个函数里面包着另一个函数, 那么可以按F11进入该函数中
  5. GIF截取工具: LICECap

  6. dropdown-menu元素如果要是通过其他方式来控制其隐藏的话,那么之后再点击的话就不会再响应了。 →_←

2016-03-18

  1. 知乎上看到的如何不使用循环创建一个长度为100的数组, 并且数组项的值要等于其索引, 原文地址

    '​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​​'.split('').map(function (v, i) { return i; }); // 关于这里的第一个''其实并不是一个简单的引号o(╯□╰)o , 零宽空格是个什么鬼
    
    Array(100).fill('naive').map(function (v, i) { return i; }); // Array.fill是ES6的语法
    
    // 通过生成器
    function* ary(i) {
      yield i;
      if (i < 99) {
        yield* ary(i + 1)
      }
    }
    Array.from(ary(0));
    
    // 使用递归
    (function f(i) {
      return i < 0 ? []: f(i - 1).concat(i);
    })(99);

    直接使用new Array(100)生成的是稀疏数组(此时控制台打印出来的是[undefined * 100]),通过``Array.from(Array(100))``即可将稀疏数组转换成密集数组(此时控制台打印出来的是[undefined,undefined...]),然后就可以调用map并能返回期望值了。

    创建一个空的密集数组: Array.from({length: 100}); 使用`Array.apply(null, {length: 100})也是可行的。

    也可以用拓展运算符。。。[...Array(100)]

    Object.keys(Array.apply(null, {length: 100}));
    
    Array.from(Array(100).keys())
    
    [...Array(100).keys()]

    apply方法的参数可以是一个类数组对象,只要改对象带有length属性即可

  2. GitHub Pages绑定域名需要将CNAME文件同步到master分支上。

  3. 注意啊。。。return 是跳出当前函数执行环境,跳出循环使用continue或者break

2016-03-20

  1. document.body.onpagehide事件相当于是在卸载的时候触发, 而不是切换标签页的时候触发。。。。

  2. 数组去重:

    var ary = [0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, 8, 9], ary2 = [], ary3 = [];
    for (var i = 0, len = ary.length; i < len; i++) {
      if(ary3.indexOf(ary[i]) === -1) ary3.push(ary[i])
    }
    // 另外一个简单的方法就是
    [...new Set(ary)];

2016-03-21

  1. 一般来说, JS中的数组是稀疏数组, 也就是说数组元素之间可以由空隙. 创建一个稀疏数组可以通过指定数组长度来创建。 稀疏数组的空隙项在使用map或者forEach遍历的时候并不会遍历到。

  2. 创建密集数组:

    var ary = Array.apply(null, Array(3));
    // [undefined, undefined, undefined];

    这个时候就可以使用map或者forEach遍历了。

  3. 好神奇, console.log*(123)居然不会报错

  4. 其实表格布局在比较复杂的情况下还是很适用的。。。

2016-03-22

  1. 下面这段代码:

    var name = (function () {                          // 这里直接使用name的话, 最后打印name得到的结果是'object Object', 换成name之外的变量名的时候就会正常反应。
      var _name = 'Jason';
      return {
        setName: function (value) {
          _name = value;
        },
        getName: function () {
           return _name;
        }
      }
    })();
    name; // 'object Object'
    typeof name; // 'string'

    这里的问题是为什么把name作为全局变量的话就会出问题? 如果把name 换为Name或者其他名字的话就没有问题。 其实这里的问题是, name貌似只能够作为一个字符串使用, 如果不是字符串,那么引擎会自动调用对象的valueOf或者toString()方法来将其转化为字符串。 如下:

    var name = (function() {})();
    name  // ‘undefined' 这里原本只应该是undefined的, 但是最后undefined被转换成了字符串。
    window.name = 5; // "5"
    window.name = false; // "false"

    这表明window.name的值总是会被强制性地转化为字符串, 所以, 不要使用name作为全局变量。

    当然, 在一个函数里面的话则不会存在这种情况

2016-03-23

  1. DELETE请求没有请求体, 具体请求数据是加在query里面的来着。
  2. 数字加数字得到的会是数字啊→_← 在用变量拼接字符串的时候尤其要注意, 如果变量是数字的话。。 可能一不小心就踩了个大坑。

2016-03-24

  1. cloneNode()可以接收参数(布尔值), 表示是否执行深拷贝, 如果执行深拷贝的话, 就会复制节点及其整个文档树。

    var someNode = document.createElement('p');
    someNode.innerHTML = 'test';
    
    var node2 = someNode.cloneNode();
    node2; // <p></p>
    
    var node3 = someNode.cloneNode(true);
    node3; // <p>test</p>

2016-03-27

  1. 关于基本包装类型

    // 返回的是一个字符串, 相当于直接定义var s = 'Jason', 对该变量定义属性是无效的
    var s = String('Jason'); // 转型函数
    typeof s; // 'string'
    var b = String('Jason');
    b === s; // true
    // 返回的是一个对象, 可以对其设置属性
    var t = new String('Jason'); // 构造函数
    tyoeof t; // 'object'
  2. 正则表达式w表示匹配一个单字字符, 可以是字母, 数字和下划线, 所以如果只是匹配字母的话可以使用str.match(/[a-zA-Z]/g)

  3. JS去掉首尾空格:

    var myTrim = function (str) {
      return str.replace(/^\s+|\s+$/g, '');   // 这里要执行全局匹配才能保证能够将所有的前置后置空格都替换掉
    }
  4. 个人博客主页(username.github.io)默认就是使用的master分支, 无需切换到gh-pages

2016-03-28

  1. 调试程序的时候应该从错误入手
  2. github客户端切换分支的时候如果要是突然多出很多文件, 可能只是因为它一时没有反应过来而已, 只需要discard changes然后过一会儿再切换分支即可。

2016-03-29

  1. Backbone.Collection create的时候,第一个参数为模型的数据, 第二个参数为相应的条件。

    this.collection.create(this.model.toJSON(), {
       wait: true // 表示等待服务器端响应 。。。
       /* silent: true,
       success (model) {
         console.log(model);
       }*/
     });
  2. 使用!操作符的时候要注意优先级的问题啊。。。

    if (!res instanceof Array)   return res; // 这里的!只会对res生效→_←
    if (!(res instanceof Array)) return res; // 使用括号提升优先级

2016-04-01

  1. 通过[data-]属性来设置值的时候是通过ele.dataset来设置的, 而jQuerydata方法的设置值和取值也是通过dataset来进行的, 所以如果通过直接修改DOM元素特性来修改data-属性的话, 表面上看起来变了, 但是dataset里面的值并没有变。
  2. data可以用来在元素上面携带任何属性的数据。
  3. 关于jQuery的data 和attr源码应该好好看一下。

2016-04-01

  1. momentformat方法在显示17:55的话应该使用format('HH:mm')

2016-04-01

  1. ERROR -4048没有权限。 用管理员身份运行。

2016-04-01

  1. 在提交代码的时候如果要是出现了index.lock已存在的信息导致新的版本不能提交的话, 那么到.git文件夹下手动将index.lock删除掉, 很多时候如果要是使用客户端不能够获取到完整的错误信息的话, 那么可以使用命令还来完成相应的操作, 毕竟命令行里面的话信息会比较全面。

###2016-04-02

  1. setTimeout和setInterval可以有多个参数, 其中第一个参数是需要异步执行的函数,第二个参数是时间, 可以为数字也可以为字符串, 如果是字符串会内部转化为数字再尝试执行, 如果不能转化为数字, 将会转化为0。 从第三个参数开始, 其余的参数可以作为参数被传入需要异步执行的函数内部。使用这个方法的话就可以每次使用到timeout或者interval的时候都需要现在外部声明一个变量, 比如var self = this或者var _this = this这种, 直接作为第三个参数传进去,然后在回调的第一个参数里获取就行了, 这样子的话, 会不会减少闭包的产生呢??

  2. 关于函数表达式

    var name = function () {
      console.log('jiangxi')
    };
    // undefined
    
    var name = function () {
      console.log('jiangxi')
    }();
    // jiangxi
    // undefined
    
    var name = (function () {
      console.log('jiangxi')
    })();
    // jiangxi
    // undefined

    也就是说这里表达式右边定义函数的时候, 函数体用不用括号包裹效果都是一样的。 因为括号只是起到了一个提升优先级的作用。 而在函数声明的时候,

  3. Array.apply(null, Array(100))相当于是Array(undefined, undefined, undefined, ...);所以, 最后得到的就是密集数组。

  4. Promise()

     function test (time) {
       return new Promise((resolve, reject) => {
         setTimeout((time) => {
           console.log(time);
           resolve(); // 一定要加这句话, 不然无法触发状态改变事件
         }, time, time);
       });
     }
     test(100).then(() => {
       return test(200);
     }).then(() => {
       return test(300);
     }).then(() => {
       return test(400);
     }).then(() => {
       return test(500);
     }).then(() => {
       return test(600);
     }).then(() => {
       return test(700);
     }).then(() => {
       return test(800);
     });

2016-04-04

  1. constlet在全局声明的变量不会挂载到全局对象window上面, 这个非常重要!!!

  2. constlet没有变量声明提升

  3. for infor of每次都会绑定新的执行环境。 所以可以使用for (const key in obj)

  4. 关于new操作符。

    var doSomeThing = function doSomeThingElse () {};
    doSomeThing.name; // doSomeThingElse;
    function Person (name) {
      this.name = name;
    }
    var person = new Person('Jiangxi'); // 返回一个新的对象
    var person2 = Person('Jiangxi'); // 无返回值, 函数里的name属性挂载到了window上面。

    JS中的函数具有两个不同的方法, [[call]][[Construct]], 当调用函数的时候没有使用new操作符, 那么[[call]]方法将会被执行, 当使用new操作符来调用的时候,[[Consturct]]方法将会负责创建一个新的对象,并将函数中的this指向当前对象。

    需要注意的是, 不是所有的函数都具有[[Construct]]方法, 箭头函数就不能作为构造函数使用。

  5. 箭头函数:

    • 箭头函数的this, super, arguments, and new.target的值, 由距离他最近的非箭头函数的函数所决定。

    • 不能使用箭头函数的情况。

      • 没有原型。箭头函数不存在原型对象, 所以不能使用new 操作符。
      • 不能改变this
      • 没有arguments对象。
    • 如果要让函数体返回一个对象的话, 应该用括号来将花括号包围起来。 如:

      // 因为花括号通常表示一个语句块儿, 所以如果没有用括号来包裹的话, 会认为需要执行里面的语句, 但是里面实际上是一个对象, 不能执行所以就会报错。
      // 所以, 在返回值是一个对象的时候, 需要用小括号将花括号包裹起来。
      var getTempItem = id => {id, name: 'temp'} // Uncaught SyntaxError: Unexpected token :
      
      var getTempItem = id => ({id, name: 'temp'}); // 正确。
    • 箭头函数的IIFE写法:

      let person = ((name) => {
        return {
          getName: function () {
            return name;
          }
        }
      })('Jiangxi');
      // 注意, 这里包裹函数的小括号必须要在参数前面而不能包含参数, 这是与常规函数不同的地方
    • 箭头函数里的this是不能够通过call, apply或者bind来改变的, 但是依然可以使用这三个方法来传递参数,只是不能对this产生影响而已。 使用bind会创建一个新的函数。

       window.age = 12;
       var obj = {
         age: 22,
         sayAge : () => {
           return this.age
         }
       };
       obj.sayAge(); // 12 因为箭头函数的this指向的是其向上追溯的第一个非箭头函数内的this, 所以这里就是指向window而非obj对象。
    • 箭头函数不具有arguments对象, 如果尝试访问arguments对象的话, 一般会返回其包含函数的arguments对象

    • 要触发ES6的尾调用优化的话:

      • 必须要有return语句
      • return语句里不能包含其他操作, 只能是函数的执行结果。
      • 如果将要返回的结果用变量存储起来, 再返回这个变量的话, 也不会触发尾调用优化。
      • 总的来说, 只有当函数结果能够被立即返回的时候才会触发尾调用优化。
      • 不能是闭包
      • 尾调用的值是以函数值的形式返回的。
      // 以下函数不会触发尾调用优化。 因为在最后返回的时候进行了多个操作
      function factorial (n) {
        if (n <= 1) return 1;
        return n * factorial(n - 1)
      }
      // 改写后的函数就能够触发尾调用优化。
      function factorial (n, p = 1) {
        if (n <= 1) return 1 * p;
        let result = n * p;
        return factorial(n - 1, result);
      }
  6. 对象。

    • 对象方法简写:

      var obj = {
        sayName () {}, // 此时sayName的name属性即为sayName
        sayName2: function () {} // sayName2的name属性为''
      };

2016-04-05

  1. Object.getOwnPropertyNames()会返回对象的可枚举属性的键名组成的数组, 该数组始进行排序后的, 数字在前, 字母在后。

  2. 对象结构。。。。 翻译不过来了→_←

let node = {
  name: 'Node',
  id: 12
};
var {name, id} = node; // 同时声明name, id变量
({name, id} = node) // 返回值是node对象,并且同时生命了name, id变量。
// 当使用这种表达式的时候,如果等号右边是`undefined`或者`null`的时候就会报错。 因为任何尝试访问`null`或者`undefined`的属性的语句都会报错。

let node  = {
  name: 'Node',
  version: '0.12.0',
  loc: {
    start: {
      line: 0,
      column: 0
    },
    end: {
      line: 1,
      column: 1
    }
  }
}
let {loc : {start}} = node;
loc; // ReferenceError: loc is not defined
start; // Object { line: 0, column: 0 }
  1. 使用ES6的REST来克隆数组。
let colors = ['blue', 'red'];
var cloneColors = [...colors];
cloneColors; // Array [ "blue", "red" ]
cloneColors === colors // false;
// 解构赋值
function setCookie(name, value, {secure = false, path = '/', domain = 'example.com', expires = +new Date() } = {}) {
  console.log(`you wanna set cookie ${name} = ${value}, and the secure is ${secure}, path is ${path}, domain is ${domain},expires is ${expires}`);
}
  1. Symbol是一种基础的数据类型。

    var sym = Symbol('str');
    typeof sym; // "symbol"

    因为Symbol是基本数据类型,所以如果对Symbol使用new操作符的话将会抛出异常。

    要创建Symbol的实例可以通过new Object(your Symbol)来创建。但是这并没有多大的用处→_←。

    Symbol接收一个可选的参数来对其进行描述, 但是这个描述符并没有访问属性的权利, 它只是为了方便调试而已。

    Symbol.for()接收一个参数,该参数同时也会作为描述符。 在使用这个方法的时候, 会首先去查找全局注册的Symbol, 如果存在, 则返回, 如果不存在, 则新建并返回。

    Set实例化的时候传递参数需要是一个数组。 如: new Set([1,2,3,4,5])

    SetforEach方法。 forEach的回调函数的参数里面第一个参数和第二个参数是相等的, 都表示set在那个位置的值,第三个参数是set本身。

    var processor2 = {
      output (value) {
         console.log(value);
      },
      process (dataSet) {
        dataSet.forEach(function (item) {
          this.output(item)
        }, this); // 如果这里不传递this的话,this指向的是window, 如果使用箭头函数的话, 则无需传递this,this指向的是当前对象。
      }
    }

    使用new Set(arr)可以将数组转化为Set, 使用[...Set]可以将set转化为数组。

    数组去重:

    var arr = [1, 2, 3, 4, 5, 6, 7, 1, 23, 3, 4, 5, 6];
    arr = [...new Set(arr)];

    WeakSet只能保存对象类型, 如果保存类型不是对象而是基础类型的话, 就会报错。

    var weakSet = new WeakSet(), key = {};
    weakSet.add(key);
    weakSet.has(key); // true
    key = null;
    weakSet.has(key); // false

    只有在考虑到要使用对象作为键值的时候才使用weakMap或者map. 而使用weakMap则是更好的选择。

2016-04-07

  1. iterator

    function createIterators(items) {
      var i = 0;
      return {
        next: function () {
          var done = i >= items.length ? true : false;
          var value = done ? undefined : items[i++];
          return {
            done: done,
            value: value
          }
        }
      }
    }

2016-04-08

  1. 判断一个对象是否可迭代可以使用以下方法:

    function isIterable (obj) {
      return typeof obj[Symbol.iterable] === 'function';
    }

    以上函数通过检测默认的迭代器是否存在来判断对象是否可迭代。

2016-04-08

  1. 关于class
    • class声明不同于函数声明,他们没有声明提升。 同时class声明也是存在暂时性死区的。

      // 通常如果不使用var来声明变量而直接为变量赋值的话变量会变成全局变量
      // 但是这里因为存在TDZ, 所以在语句没执行到class之前,class声明的Person都是不可用的。
      Person = 123;
      class Person {
        constructor (name) {
          this.name = name;
        }
        sayName () {
          console.log(this.name)
        }
      }
    • class声明的代码都是自动在严格模式下执行的, 并且没有办法使得他们脱离严格模式而执行。

    • 所有的方法都是不可枚举的。

    • 所有的方法都是不具有[[construct]]内部方法的。 所以不能使用new操作符, 如果尝试使用将会抛出错误。

    • 不使用new操作符来调用class的话, 将会抛出错误

    • 定义静态成员。

       class PersonClass {
         constructor (name) {
             this.name = name;
         }
         static create (name) {
             return new PersonClass(name);
         }
         sayName () {
             console.log('My name is ' + this.name);
         }
       }
       var person = new PersonClass.create('Jason'); // 静态方法是直接通过class定义的来访问的, 不能通过实例来访问。
       function Rectangle(length, width) {
         this.length = length;
         this.width = width;
       }
       Rectangle.prototype.getArea = function() {
         return this.length * this.width;
       };
       function Square(length) {
         Rectangle.call(this, length, length);
       }
       Square.prototype = Object.create(Rectangle.prototype,
         constructor: {
           value:Square,
           enumerable: true,
           writable: true,
           configurable: true
         }
       });
       var square = new Square(3);
    • 关于 extends

       class Square extends Rectangle {
         constructor(length) { // constructor里面的参数是实例化的时候传入的参数(对应这里的new Square()的时候传入的参数)。
         // same as Rectangle.call(this, length, length)
         super(length, length); // 这里的super的参数将会传入父类e的construtor的参数里。
         }
       }

2016-04-11

  1. Array.from.
    • 可以用于将类数组对象转换为数组对象。

    • 在转换的时候第二个参数可以对数组进行map操作。

      Array.from([1,2,3,4], item => item * 2); // [2,4,6,8]
    • 如果第二个参数是一个对象的方法的话, 可以用第三个参数来指定函数执行的上下文。

       var helper = {
         diff: 1,
         add (value) {
           return value + this.diff;
         }
       };
       var diff = 2;
       Array.from([1,2,3,4,5], helper.add); // [3, 4, 5, 6, 7]
       Array.from([1,2,3,4,5], helper.add, helper); // [2, 3, 4, 5, 6]
    • Array.from可用于类数组对象和具有迭代器接口的对象。

       let numbers = {
         *[Symbol.iterator]() {
           yield 1;
           yield 2;
           yield 3;
         }
       };
       let numbers2 = Array.from(numbers, (value) => value + 1); // [2, 3, 4]

2016-04-12

  1. 关于ArrayBuffer

    • 创建ArrayBuffer

      var buffer = new ArrayBuffer(10);
    • 创建view

      // 第二个参数表示offset, 第三个参数表示的是截取长度。
      var view = new DataView(buffer, 5, 5); // 第二三可参数是可选的, 当提供第三个参数的时候, 那么二三个参数加起来的和不能大于`buffer`的`byteLength`, 不然就会报错。
  2. Promise的执行器(定义时的函数参数)是立即执行的。

     var promise = new Promise((resolve, reject) => {
       console.log('Promise')
       resolve();
     });
     console.log('hi');
     // Promise
     // hi

2016-04-13

  1. 碰到的一个问题。

    // 数据结构如下, 如果res中一个数组项的messageType是'29', 那么将整个数组中的hrefC与该数组项的hrefC值相同的数组项连带其本身都删除掉, 并且打印出删除项id。如下, 数组第二项的type为29, hrefC为71750, 那么就需要将整个数组中hrefC为71750的项删除掉, 并且打印出他们的id.
     const res = [{
       messageType:"4",
       hrefC: "71750",
       id: '1'
     }, {
       messageType:"29",
       hrefC: "71750",
       id: '2'
     }, {
       messageType:"4",
       hrefC: "71749",
       id: '3'
     }, {
       messageType:"29",
       hrefC: "71749",
       id: '4'
     }, {
       messageType:"4",
       hrefC: "71751",
       id: '5'
     }, {
       messageType:"29",
       hrefC: "71751",
       id: '6'
     }];

    demo

2016-04-14

  1. select不支持伪类, select里面也不能有option之外的其他元素

2016-04-14

  1. 如果要是https下的网页内容里面包含了混合内容(mixed-content:displayed), 那么网站前面的https将不会是绿色的, 这个可以通过chrome的security工具来查看(Mixed Content)。

2016-04-14

  1. ctrle.ctrlkey, commande.metaKey

2016-04-27

  1. 关于dropdown
.dropdown
  .dropdown-toggle [data-toggle='dropdown']
  .dropdown-menu
    .dropdown-item
    .dropdown-item

2016-04-29

  1. 创建100个'x'组成的字符串。 new Array(100).join('x')
  2. 'x'.repeat(100);

2016-05-03

  1. 在通过AJAXpost数据的时候, 需要设置请求头:

    xhr.setRequestHeader('Content-type', 'application/x-www-urlencoded; charset=utf-8');
  2. 关于表单数据的ajax提交: 如提交内容为以下对象:

    var data = {
      username: 'Jason',
      password: 123456
    }

    那么要实现表单式提交首先需要设置请求头, 如上面所示

    然后格式化数据:

     function formatFormData (obj) {
       var ary = [];
       for (var key in obj) {
         ary.push(key + '=' + obj[key]);
       }
       return ary.join('&');
     }
     formatFormData(data); // 'username=Jason&password=123456';

    这样就能正确的发送表单数据了。

  3. 数据库连接的时候如果显示mysql_connect() is not a function的时候, 那么可能是php.ini中的扩展(extension: mysql.dll; extension: <mysqli class="dll"></mysqli>)没有启用, 或者说是扩展的路径名(extension_dir: )错误。

  4. PHP要相应JSON数据的话, 需要对数据进行json_encode()然后echo处理。

2016-05-04

  1. CYGWIN是一个可以在windows上使用Linux命令的环境, 通过它来安装fish的时候需要在安装过程包选择中选择fish才行, 然后通过他的命令行输入fish进入fish

2016-05-05

  1. cygwin 默认是挂载了磁盘的, 通过访问/cyqdrive/your device就可访问到对应的磁盘分区
  2. df用来查看挂载点

2016-05-09

  1. 在访问nginx服务器上的.php出现no input file specified的时候, 在location里面添加root, 并且将scriptfile后面的设为$document_root
     location ~ \.php$ {
       root           D:\\nginx-1.6.0\html;
       fastcgi_pass   127.0.0.1:9000;
       fastcgi_index  index.php;
       fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
       include        fastcgi_params;
     }
  2. document.documentMode判断是IE几
  3. 如果.chm的文件打开后没有内容, 那么右击文件, 点解除锁定就行了。

2016-05-10

  1. 关于字符串的replace方法:

     var str = '今天是个好天气';
     // 也就是replace方法的第二个参数可以是一个函数, 函数传入参数是前面匹配到的字符串
     str.replace(/[今天]/g, (a) => {
       return a.repeat(5);
     });
     // "今今今今今天天天天天是个好天天天天天气"

2016-05-11

  1. IE10和IE11抛弃了条件注释。。

  2. 在一个执行环境内, 对于使用const或者let声明的变量,在语句没执行到的时候, 不能进行任何访问行为。 包括调用typeof操作符

    When a JavaScript engine looks through an upcoming block andfinds a variable declaration, it either hoists thedeclaration to the top of the function or global scope (for var) or places the declaration in the TDZ (for let and const).Any attempt to access a variable in the TDZ results in aruntime error. That variable is only removed from the TDZ,and therefore safe to use, once execution flows to the variable declaration.

2016-05-12

  1. 通过给a标签添加download属性,即可实现在点击的时候直接下载href属性指向的资源。

2016-05-13

  1. removeEventListeneraddEventListener的三个参数必须相同,才能保证能够正确的移除对应事件。

2016-05-25

  1. obj.selectionStart只针对input, textarea等元素, 不适用于contenteditable元素

2016-05-26

  1. false && true || true得到的结果是true, 首先false && truefalse, 然后, false || true为true
  2. 回车的断行事件是在keydown结束后和keyup结束前触发的, 所以如果要在按回车的时候阻止默认事件, 应该在keydown里面进行。

2016-06-23

  1. 关于this
// with (global)
var a = {
  a: this, // window
  data: {
    a: this // window
  },
  sayName () {
    console.log(this); // a Object {}
  }
}

2016-06-30

  1. /\w/.test(123)得到的结果是true, 因为\w匹配的是字母数字和下划线之中的任意一个

2016-07-01

  1. forEach里面不能使用continue, break语句, 虽然能够使用return并且不会报错, 但是实际上即使满足条件的话也不会跳出循环, 而是会继续执行下去。这里主要原因是forEach接受的参数只是一个回调罢了。 可以尝试自己写一个函数来实现forEach, 然后就会简单明了。

    Array.prototype.myForEach = function (fn) {
       const len = this.length;
       for (let i = 0; i < len; i++) {
          fn(this[i], i, this); // 而这里就是forEach里面的函数所执行的东西, 简而言之, 它只是一个函数, 而非循环, 所以不能使用continue, break
          // 另外, 在里面使用return也仅仅是跳出当前执行的函数而已, 外部并不会停止执行
       }
    }

2016-07-04

  1. 通过e.path来确定点击元素的层次是一个不错的办法, 但是兼容性是一个问题。

2016-07-06

  1. 关于函数默认参数, 只有在给调用函数的时候没有在对应位置上传入参数的时候, 默认参数才会生效。也就是说, 判定默认参数是否生效的原则是是否传递该参数, 而不是该参数的值是否为true
function say (a, b = 2, c = 3) {
  console.log(a, b, c);
}
say(1); // 1 2 3
say(1, false, '') // 1 false ''
  1. bind的优先级是要高于callapply的。
window.name = 'Jason';
var obj = {
  name: 'Jason2',
  sayName: function () {
  console.log(this.name)
  }.bind(this)
};
var obj2 = {
  name: 'Daisy',
  sayName: function () {
    obj.sayName.call(this);
  }
};
obj2.sayName(); // Jason;
  1. 对象方法的简写形式里不能使用bind, 但是非简写情况下是可以使用的。
// 下面这种写法会导致错误
var obj = {
  name: 'Jason',
  sayName () {

  }.bind(this) // error
};
// 可以采用这种非简写写法
var obj = {
  name: 'Jason',
  sayName: function () {}.bind(this)
};
  1. 关于函数参数解构
// 这里的目的原本是声明函数的第一个参数为options, 并且声明变量options的指定属性为name,age, 在没有传递参数的情况下, 默认设置为一个对象以避免报错
// 但是这样的声明最后会报错, 说options未定义

function sayName ({ name, age } = options = {}) {
  console.log(name, age, options);
}

不知道有什么方法能够达到上面的目的, 暂时没想到, 说明基础还不够巩固, 该继续滚回去看书了。

所以老老实实的用其他方法吧。

function sayName (options = {}) {
  const { name, age } = options;
  console.log(name, age, options);
}

2016-07-07

  1. 当一个节点从dom中移除的时候将会触发其blur事件。 所以此时如果要是绑定了事件处理函数的时候, 需要慎重处理。

2016-07-25

  1. 关于selection
const sel = window.getSelection(),
        range = sel.getRangeAt(0), // 获取当前光标所在的范围
        span = GET_AT_SPAN(); // 生成一个DOM节点

    range.insertNode(span); // 插入
    sel.addRange(range);    // 添加范围
    sel.collapseToEnd();    // 光标移动到最后

2016-07-26

  1. splice删除元素之后返回的是一个数组

2016-07-29

  1. 使用inline-block进行布局的时候, 如果在某些情况下错位了, 可能是其默认间距造成的问题, 设置font-size

2016-08-03

  1. webkit系浏览器下检测页面滚动使用document.body.scrollTop, 其他浏览器下应该使用document.documentElement.scrollTop;

2016-08-03

  1. 字体及字间距