2015年前的学习笔记

2020-02-16  本文已影响0人  JUN仔_8cea

///////////////////////////////////////////////////////////////////////////////

jquery插件中预防$冲突的办法:

(function($){ //...  })(jQuery);

把jQqury传递给插件,用$来获取该参数,这样其他框架中即便占用了$也不影响jQ插件里对$的使用

///////////////////////////////////////////////////////////////////////////////

setInterval和setTimeout函数部分带引号和不带引号的区别:

var a=0;

1、setTimeout("hallo(a)",300);//可以传参数a,并且该函数会在300ms之后执行;

2、setTimeout("hallo",300);//并不会被执行

3、setTimeout(hallo,300);//不可传参数a,300ms之后执行

4、setTimeout(hallo(a),300);//可传递参数a,立即执行。setTimeout将变得无意义

5、setInterval(hallo(a),300);//立即执行,setInterval变得无效,不会轮询

结论:a、不带引号的,不能带括号,带引号的必须带括号。2、4、5实际是错误的写法;b、要想在规定的时间里用setInterval和setTimeout的回调函数来执行函数并且又想传递参数,最好的方式就是使用方法1、"hallo(a)"

///////////////////////////////////////////////////////////////////////////////

网页更新防止缓存方法:

1、<meta forua="true" http-equiv="Cache-Control" content="max-age=86400"/>

其中max-age为获新的时间,86400表示一天之后获新,获新内容为所有js、css和image等资源文件

///////////////////////////////////////////////////////////////////////////////

解决ie8不支持媒体查询:

<!--[if lt IE 9]>  

    <script src="http://css3-mediaqueries-js.googlecode.com/svn/trunk/css3-mediaqueries.js"></script>  

<![endif]-->  

///////////////////////////////////////////////////////////////////////////////

让一个元素不再浮动的css:float:none;

///////////////////////////////////////////////////////////////////////////////

@media查询中,max-width和max-device-width区别:

width指可视宽度,横屏时,会变宽。device-width是设备自带的属性,不会变化。另外,height在有菜单栏的浏览器下会比device-height小

判断横屏竖屏方式:

@media (max-width:XXXX) and (orientation:landscape | portrait)。其中landscape表示手持,portrait表示横屏,其原理就是比较width和height。

///////////////////////////////////////////////////////////////////////////////

千万不要将float与&nbsp;

原则是:少用&nbsp;

///////////////////////////////////////////////////////////////////////////////

函数前面加上感叹号“!”有什么用?

原因:形如 function(){}()的函数是无法执行的,需要用括号括起来把函数体编程一个表达式:(function(){})()

但是函数前面加上!之后,函数就会被正确的解析和调用:!function(){}();这样的方式,效率似乎更高。另外,+、-也有类似功能:

+function(){}()、-function(){}();

参见:在bootstrap中,自动执行的函数的写法是:

!function($){}(window.jQuery);

///////////////////////////////////////////////////////////////////////////////

几个冷知识:

1、但凡有id的dom,会自动生成一个全局对象,不用document.getElementById("id")或$("#id");

html:<div id="hallo">aaa</div>

js:console.log(hallo.innerHTML);=>aaa

   console.log($(hallo).html());=>aaa;

2、

///////////////////////////////////////////////////////////////////////////////

垂直居中的解决方案

单行:

1、vertical-align:middle;line-height:100%;

多行、未知高度:

1、

内层:

position:relative;

top:50%;transform:translateY(-50%);

top:50%;-webkit-transform:translateY(-50%);

只支持ie9以上

2、

外层:display:table;

内层:diaplay:table-cell;vertical-align:middle;

///////////////////////////////////////////////////////////////////////////////

要想知道一个对象有什么特性及其值,可以使用以下方法:

for(var i in obj){

console.log(i+":"+obj[i]);

}

通过此方法,意外的获知:

对于<a id="hallo" href="http://www.baidu.com/a/b/c?id=123"></a>,可以获得如下参数

1、a标签(对象)的属性中有host:主机名(含接口),hostname不含接口,如:192.168.0.124:8001是host,而192.168.0.124。

2、hallo.pathname=>/a/b/c

3、hallo.protocol=>http

4、hallo.host=>www.baidu.com

5、hallo.hostname=>www.baidu.com

6、hallo.origin=>http://www.baidu.com

7、hallo.search=>?id=123"

///////////////////////////////////////////////////////////////////////////////

如何利用toString来创建字符和数字结合的编码:

console.log(generateRandomAlphaNum(25));//创建25位混排编码

        function generateRandomAlphaNum(len) {

            var rdmString = "";

            for (; rdmString.length < len; rdmString += Math.random().toString(36).substr(2)) {

                console.log(rdmString);

            }

            return rdmString.substr(0, len);

        }

///////////////////////////////////////////////////////////////////////////////

高效率的位操作符:

(12.4/4.13)|0=>相当于:Math.round(12.4/4.13)

~~(12.4/4.13)=>相当于:Math.floor(12.4/4.13)

!!(a)=>快速转换为布尔值,相当于:boolean(aa);如:!!window=>true

///////////////////////////////////////////////////////////////////////////////

自定义console.log的样式:

function resetConsoleStyle(cssStyle) {

    var _log = console.log;

    console.log = function () {

        _log.call(console, '%c' + [].slice.call(arguments).join(' '), cssStyle);

    };

}

resetConsoleStyle("color:fff;background:#000;");

console.log("aaa")=>aaa

///////////////////////////////////////////////////////////////////////////////

交换两个变量的值,不用第三个变量暂存

1vara=1,b=2;a=[b,b=a][0];

///////////////////////////////////////////////////////////////////////////////

关于动作的设计:鼠标移上和移 出元素产生的动画,分别为进入和离开动作

///////////////////////////////////////////////////////////////////////////////

一张图解释文档的加载和解析过程没,defer和async的区别

(绿线的终点为DOMContentLoaded的状态)

///////////////////////////////////////////////////////////////////////////////

caller是函数对象的一个属性,他指向调用该函数的函数,可以用fn.caller.toString()将函数转化为字符串

callee是arguments对象的一个属性,他指向当前函数体

注:caller和callee都是在函数执行时才产生

    function callDemo() {

        if (callDemo.caller) {

var a=callDemo.caller;

            alert(a);

        } else{

            alert("this is a top function");

        }

alert(arguments.callee);

    }

    !function handleCall() {

        callDemo();

    }();

输出:

caller=>function handleCall(){callDemo();}

callee=>

    function callDemo() {

        if (callDemo.caller) {

            var a= callDemo.caller;

            alert(a);

        } else{

            alert("this is a top function");

        }

        alert(arguments.callee);

    }

二者结合:arguments.callee.caller=>调用此函数的函数,即callDemo函数

///////////////////////////////////////////////////////////////////////////////

delete obj.para=>删除obj对象中的para属性,但并不会删除属性本身;如:

obj.p={};

delete obj.p;=>只是接触了obj和p之间的关联,并没有彻底清除p。产生的问题:这并不是一种不严谨的删除方法,容易造成内存泄漏

///////////////////////////////////////////////////////////////////////////////

js中的三种编码方式:

escape:将所有ASCII表以外的字符串进行编码。解码方式:unescape

encodeURI和endoceURIComponent相对来说更强大,对应解码方式分别为:decodeURI和decodeURIComponent

推荐方式:endodeURIComponent

注:document.cookie没有进行编码,因此,通常情况下建议对cookie进行编码——encodeURIComponent(getCookie(aaa));

///////////////////////////////////////////////////////////////////////////////

webworker的总结:

使用webworker另起一个线程:

加载顺序:网页js+css加载完成后,才呈现页面,这样会导致页面加载很慢,于是,可以把那些加载过慢的js模块单拿出来放到异步线程中,这样,页面可以正常显示,而不会因为过慢的模块导致页面加载变慢

语法如下:

新建:var wk=new Worker("XX.js");

分线程XX.js中回传结果:postMessage(a);//假设此处a的值为1

主线程添加监听:wk.onmessage=function(event){

console.log(event.data);//获取返回来的结果,打印1

}

关闭线程:wk.terminate();//通常是在获取完event.data之后进行关闭

浏览器支持:ie10以下不支持

///////////////////////////////////////////////////////////////////////////////

this深入解析

1、this定义:this所在域(函数)被看成是哪个对象的方法,this指代的就是那个对象

2、全局中的this都是指的window

var obj={

    x:0,

    y:function(){

        var _this=this;

        setTimeout(function(){

//this指window,因为setTimeout是window的方法

            //_this指obj

        })

    }

}

3、call、apply的本质:重新定义函数的执行环境,即重新定义了函数中this的指向

function A(n,m){

//this指向待定

}

var obj={};、

A.call(obj,1,2);//将A看成是obj的方法,函数中this自然而然指向obj

这里提一下bind。bind也是javascript原生的函数,ie9+可支持,与call、apply同样是改变this的指向,区别在于使用方法:

bind返回的是函数体,后两者返回的是执行结果,即fun和fun()的区别

obj.y.call(o,1,1)=>等价于obj.y.bind(o,1,1)()=>等价于obj.y.bind(o)(1,1);

bind方法中,会优先调用bind(paras)中的参数,当发现bind(paras)中参数不足时候,才会去依次调用后面(paras)的参数,obj.y.bind(o,1)(2,3)=>如果obj.y需要的参数是2个,则此时使用的参数是(1,2),如果需要三个参数,则会使用(1,2,3)

bind常可以在setTimeout和setInterval中用到

var obj={};

obj.stv=setInterval(function(){

this=>指向obj而不是window 

}.bind(obj),100);

///////////////////////////////////////////////////////////////////////////////

曾经一直困扰我的一个问题:body的高度来源于其内容的高度,故无法满屏

解决办法很简单:html,body{height:100%;}。结果:当body内元素不足body的高度时,html和body高度为屏幕高度,当body内元素大于body高度时候,body的offsetHeight不变,始终等于document.body.clientHeight。而document.body.scrollHeight会随着页面内容的增加而自动扩张

///////////////////////////////////////////////////////////////////////////////

为一个dom添加事件监听之后立即取消该事件监听的精致写法:

s.addEventListener("load",function(){

this.removeEventListener("load",arguments.callee,false);

})

///////////////////////////////////////////////////////////////////////////////

css、js、dom、img加载顺序:

dom树按顺序加载,遇到css文件(link标签)时,dom会继续执行下去,而css标签异步进行加载。

dom树遇到js文件(script标签)时,会等到js加载并执行完后再继续下去。而动态加载进来的js则不会阻塞dom

dom遇到img标签时,会继续执行下去,图片则异步进行加载。并且图片会被延迟加载,直到css加载完成之后才加载图片(因为浏览器不知道图片此时应该以什么样式进行显示)——有待考证

window的onload、window的DOMContentLoaded、document的ready顺序:

DOMContentLoaded是指所有dom加载完成,而js(在没有defer、async的干扰时)是引入文档中作为文档的一份子,因此浏览器解析script标签时就会将其加载进来,DOMContentLoaded状态下所有的js都已经加载完毕

而img、link-css则会异步加载,而window的onload是指所有的img、link-css等资源加载完成后执行,因此onload比DOMContentLoaded慢。

通常,在移动端,onload不如DOMContentLoaded更优

其实,DOMContentLoaded就相当于在html的最底部执行

html+script=>window DOMContentLoaded=>img、link-css=>window onload

jquery中的$(document).ready(function(){})和$(function(){})等于window的DOMContentLoaded

别人给出的建议:

1、由于图片会在css加载完成后载入,CSS样式表影响了图片的加载速度,然而JS不会影响,如果想让图片尽快加载,就不要给图片使用样式,比如宽高采用标签属性即可。

2、JS的加载执行速度影响了DOMContentLoaded事件的触发时间,如果想要尽快触发DOMContentLoaded事件,就将次要的JS采用动态加载的方式加载吧。

///////////////////////////////////////////////////////////////////////////////

canvas变形方法:

canvas.translate(x,y):定义canvas的(0,0)坐标点(以下所有方法都是相对于此点进行变形)

canvas.scale(scaleWidth,scaleHeight):放大倍数,宽度和高度倍数都不可少

canvas.rotate(angle):旋转角度

canvas.transform(a,b,c,d,e,f):

canvas.setTransform(a,b,c,d,e,f):

transform和setTransform中的参数解释:

a:水平缩放

b:垂直倾斜,0表示无倾斜

c:水平倾斜,0表示无倾斜

d:垂直缩放,1表示无缩放

e:水平位置偏移

f:垂直位置偏移

1、setTransform会重置0,0坐标点和其他变形为初始状态。

scale、rotate、tranform则会依据当前的状态进行相对的变形。

比如:transform和setTransform:前者会基于目前已经变形的情况进行进一步变形,而setTransform则是重置所有变形。比如,已经用scale放大了2倍,transform再放大3倍,canvas将变成6倍,而setTransform放大3倍则会重置放大倍数为3倍

2、canvas中的变形的相对点是canvas的0,0点。而css3 transform中的变形的相对点永远是元素的中心点。所有倾斜均是逆时针方向

///////////////////////////////////////////////////////////////////////////////

为某些内置对象增加方法:

String.prototype.getHallo=function(a,b){}

想调用某些内置对象的方法:

情形一:不需要改变this指向的

var getHallo=Math.pow;

console.log(getHallo(2,5));//=>32

情形二:需要改变this指向的

(1) "".substr.call(str,2);//=>cdef

或者

(2) (new String()).substr.call(str,2)//=>cdef 性质同(1)

或者

(3) var str="abcdef";

String.prototype.substr.call(str,2);//=>cdef

或者

(4) "".__proto__.substr.call(str,2)//=>cdef 性质同(3)

///////////////////////////////////////////////////////////////////////////////

关于表单元素value值:

表单中textarea和input的值均保存在dom.value中,这里的dom.value与自身的value属性并不一样。dom.value会随着onchange自动更新,而自身的value则不会。也就是说getAttribute("value")一旦<ipnut value="111"/>被赋值,则不会再改变,除非js动态改变其value值

textarea和input:

举例:

<input id="hallo" type="text" value="111"/>

hallo.value=>111

hallo.getAttribute("value")=>111

input输入222

hallo.value=>222

hallo.getAttribute("value")=>111

设置value属性值

hallo.setAttribute("value","333")

hallo.value=>333

hallo.getAttribute("value")=>333

结论:dom.value总是会自动更新,而html标签-value属性值则与data-xxx并无差别,要想改变该值,都需要setAttribute()

///////////////////////////////////////////////////////////////////////////////

用以下几行代码来解释一下作用域和bind以及闭包的应用:

首先,看一下原始形态:

var obj={};

obj.stv=setTimeout(function(){

    console.log(this); //<b>

},100);

<b>处指向window,因为setTimeout是window的对象,事实上我们希望这里指向当前对象obj

变形:

var obj={};

obj.stv=setTimeout(function(){

    console.log(this); //<b>

}.bind(obj),100);

<b>处指向obj,bind将指向做了改变

但是,我们希望不要再bind中使用obj,而是,直接用this指向当前对象,于是变形:

var obj={};

obj.stv=function(){

    console.log(this);//<a>

    setTimeout(function(){

        console.log(this); //<b>

    }.bind(this),100);

}();

咦,似乎与我们想要的结果不太一样,函数体将自动执行,<a>处和<b>的this都指向了window,这是因为该函数在定义时就被执行,并未被赋值给任何对象

再变形:

var obj={};

obj.stv=function(){

    console.log(this);//<a>

    setTimeout(function(){

        console.log(this); //<b>

    }.bind(this),100);

};

obj.stv();

这就是我们想要的结果了,但看起来好像仍然不够完美,因为,函数内部和外部环境没有分离开,于是,我们给他一个闭包

var obj={};

obj.stv=function(){

    return function(){

        console.log(this);//<a>

        setTimeout(function(){

            console.log(this); //<b>

        }.bind(this),100);

    };

}();

obj.stv();

这样,就完美了

///////////////////////////////////////////////////////////////////////////////

用call来优化笨重的上下文切换

设想一下,如果我们写一个改变dom颜色的函数,并可能会被频繁调用

如下:

function changeColor(c){

    this.style.color=c;

}

如何使用?

div1.changeColor("#f90") 肯定会报错,因为changeColor不是dom自带的方法,一般情况下,我们可能会去给dom写拓展,比如:

!function(dom){

    dom.changeColor=function(c){

        //循环、赋值。。。。

    }

}(NodeList.prototype);

或者干脆调用时将要操作的dom对象作为传过去

function changeColor(ele,c){

    ele.style.color=c;

}

第一种方法是一种封装,对于频繁使用的内容可以这么做,但是总不能对所有的涉及到dom操作的都拓展到prototype上吧,那样太不人道了

第二种方法比较low,就不细说了

用下面的方法:

function changecolor(c){

this.style.color=c;

}

调用时:changeColor.call(ele,c)

///////////////////////////////////////////////////////////////////////////////

关于函数节流:当用户通过某些操作而频繁调用某一函数时,尤其是涉及到dom重流重绘时,会导致性能浪费,于是对某些操作做一定延时处理,比如窗口resize:

var resizeTimer=null;

$(window).on('resize',function(){

if(resizeTimer){

clearTimeout(resizeTimer)

}

resizeTimer=setTimeout(function(){

console.log("window resize");

},400);

}

);

我们将函数节流成为throttle,以上是基本原理,以后细细研究

///////////////////////////////////////////////////////////////////////////////

jquery中map的应用:

场景:

<div class="hallo">1</div>

<div class="hallo">2</div>

<div class="hallo">3</div>

现在想要获取.hallo中的值并组成一个数组:

var arr=[];

$(".hallo").each(function(){

    arr.push(this.innerHTML);

});

console.log(arr);

有了map,可以更加简单:

arr=$(".hallo").map(function(){

    return this.innerHTML;

}).get();

console.log(arr);

这里的map是一个jquery封装的数组,需要用get()方法就能得到标准的数组了

///////////////////////////////////////////////////////////////////////////////

高效率canvas:

1、减少canvas状态的改变

普通方式:

for (var i = 0; i < STRIPES; i++) {

          context.fillStyle = (i % 2 ? COLOR1 : COLOR2);

          context.fillRect(i * GAP, 0, GAP, 480);

      } 

高效方式:

context.fillStyle = COLOR1;

      for (var i = 0; i < STRIPES / 2; i++) {

          context.fillRect((i * 2) * GAP, 0, GAP, 480);

      }

      context.fillStyle = COLOR2;

      for (var i = 0; i < STRIPES / 2; i++) {

          context.fillRect((i * 2 + 1) * GAP, 0, GAP, 480);

      }

2、尽量少调用canvasAPI

3、渲染范围尽量缩小,只渲染有效部分

普通:context.fillRect(0, 0, canvas.width, canvas.height); 

高效:context.fillRect(20, 20, 100, 100);

4、复杂场景使用多层canvas(但不要超过3个)

5、像素级别的操作,尽量用整数

6、动画用 requestAnimationFrame

7、渲染canvas比渲染图片更快,所以可以预先将图片渲染到隐藏的canvas中,需要使用的时候将隐藏的canvas中的图像区域取出来

8、可以用html背景的就不要用canvas做背景

9、使用的图片尽量小,且bmp格式比png格式效率更高(前者不用考虑透明度)

10、putImageData比drawImage效率高

11、预渲染,具体什么原理暂时没搞懂,先贴出代码:

普通:

var canvas = document.getElementById("myCanvas");

var context = this.canvas.getContext('2d');

var drawAsync = eval(Jscex.compile("async", function () {

while (true) {

              drawMario(context);

              $await(Jscex.Async.sleep(1000));

          }

      }))

Async().start();

      dra

w

高效:

var canvas = document.getElementById("myCanvas");

var context = this.canvas.getContext('2d');

var m_canvas = document.createElement('canvas');

m_canvas.width = 64;

      m_canvas.height = 64;

var m_context = m_canvas.getContext('2d');

      drawMario(m_context);

var drawAsync = eval(Jscex.compile("async", function () {

while (true) {

              context.drawImage(m_canvas, 0, 0);

              $await(Jscex.Async.sleep(1000));

          }

      }))

Async().start();

      dra

w

///////////////////////////////////////////////////////////////////////////////

iPhone上有一个奇怪的事件传导机制:

如果div1和div2重叠了,那么单击div1,则div2也会监听到。

解决办法:div1的单击事件加上e.preventDefault();

///////////////////////////////////////////////////////////////////////////////

关于click和touch触发顺序和抵消机制:

touchstart、touchmove、touchend、touchcancel

touchstart:手指接触屏幕即触发

touchmove:在touchstart之后移动后不断触发

touchend:手指离开屏幕触发

touchcancel:当系统停止跟踪触摸的时候触发。并非是手指离开屏幕时。比如:拖拽过程中突然按下了home键,就会触发

正常拖拽结束后只会触发touchend而不会触发touchcancel

拖拽触发的事件顺序为:touchstart=>touchmove=>touchend

点击触发的事件顺序为:touchstart=>touchend=>click

长按如果触发了选中,则touchmove不会持续触发,所以,如果事件监听比较复杂,最好添加上

另:移动端点击操作会在touchend之后相继(延时后)触发mousemove、mousedown、mouseup、click,而拖拽则不会(touchend就结束了)

///////////////////////////////////////////////////////////////////////////////

事件的一些通用属性:

1、e.bubbles:是否允许冒泡,默认为true,当使用了e.stopPropagation()方法后,变为false

2、e.cancelable:是否禁止默认事件,默认为false,当使用了e.preventDefault()方法后,变为true

3、e.target和e.currentTarget:前者是触发事件流的对象,后者是当前监听的对象,如:

<ul><li></li></ul>

$("ul").addEventListener("click",function(e){

    e.target=>点击 li 时,指 li ,点击ul时候指ul

    e.currentTarget=>点击 li 时指ul,点击ul时,指ul

});

也就是说只有当触发事件流的对象和当前监听对象一致时,target才等于currentTarget

应用场景:如果你想对某父元素进行监听但希望只有在点击该父元素时才执行监听函数,但又不想对子元素禁止冒泡,则可以在父元素处做一个判断,判定是点击了的该父元素还是冒泡过来的事件

4、e.deaultPrevented:是否禁止默认事件,默认为false,当使用了e.preventDefault()方法后,变为true

5、e.eventPhase:返回事件的阶段,1、2、3分别代表捕获阶段(EVENT.CAPTUREING_PHASE)、正常事件派发阶段(EVENT.AT_TARGET)和冒泡阶段(EVENT.BUBBING_PHASE)。上一个应用场景也可以用此属性进行判定

6、e.isTrusted:是否可信事件,非用户触发的事件,返回false,正常激发的事件为true,比如:用jquery的trigger方法代码触发事件,返回false

思考:有没有可能通过isTrusted来解决Safari中不支持自动语音播放问题

7、e.timeStamp:触发事件的时间

思考:没有必要在事件监听中用new Date()来获取当前时间,因为事件中已经有了这个属性,要时常温习旧知识

8、e.type:事件类型,不必赘述

特定事件的一些特有属性:

1、clipBoardData:剪切事件,剪切的内容

///////////////////////////////////////////////////////////////////////////////

hasOwnProperty()方法和in语句的区别:

var Person=function(name,age){

 this.name=name;

 this.age=age;

};

Person.prototype.hello=function(){

 console.log(this.name);

 console.log(this.age);

}

var p=new Person("lijun",24);

p.hello();//=>返回lijun 24

console.log(p.hasOwnProperty("name"));//=>返回true

console.log(p.hasOwnProperty("hello"));//=>返回false

console.log("hello" in p);//=>返回true

///////////////////////////////////////////////////////////////////////////////

严格模式下arguments不允许被修改:

"use strict";

function hello(a,b,c){

 arguments[2]=10; //严格模式下,此行无效

 alert(c); //若无"use strict",则返回10,若有,则返回3

}

hello(1,2,3);

///////////////////////////////////////////////////////////////////////////////

变量声明和赋值顺序:

看如下代码:

function a(x) {

    return x * 2;

}

var a=1;

console.log(a);//output:1

执行顺序为:

//声明阶段——先声明普通变量,再声明函数变量

var a;

function a;

//赋值阶段——按顺序赋值

a=function(x){

    return x*2;

}

a=1;

以上代码改成:

function a(x) {

    return x * 2;

}

var a;

console.log(a);//output:function(x){return x*2;}

///////////////////////////////////////////////////////////////////////////////

call传null:

function a() {

    console.log(this);

}

a.call(null);//output:window

这个原因可能是call函数的实现中,对参数的判断是,如果参数为null或undefined,就认为没有传参数,而没有传参数的时候上下文显然应该是window。

为了更深入理解,深入一步进行探索:

var obj={

 a:function(){

     console.log(this);

 }

};

obj.a.call(null);//output:仍然是window,而不是obj,这说明null并不预示着无传入参数,相反,null就意味着传入了window,call默认的传入参数是window,也就是说,call方法对第一个参数进行了整理。继续:

var obj={

 a:function(){

     console.log(this);

 }

};

obj.a.call(0);//output:Number

obj.a.call(false);//output:Boolean

符合上面的猜想,call的确对第一个参数做了特殊处理,它要保证第一个参数进入后以对象的形式传递给委托方法的this,而undefined和null只不过被转换成了window而已

///////////////////////////////////////////////////////////////////////////////

function中的function的归属问题,这应该算是js的一个bug:

function hallo(){

 console.log(this); //=>(1) window

 function what(){

  console.log(this); //=>(2) window

 }

 what();

}

hallo();

console.log("what" in window);//=>(3) false

console.log("hallo" in window);//=>(4) true

函数what为函数hallo的局部变量,但(2)处的this指向是window,而与此同时(3)却返回了false标明what并不被window收录为其属性

另:在严格模式下,(1)(2)处均返回undefined,而(3)处为false,(4)处为true

///////////////////////////////////////////////////////////////////////////////

css外链link标签的属性在中,stylesheet是必须的,但type不是必须的

///////////////////////////////////////////////////////////////////////////////

关于js中的两种继承方法:

function Person(name){

this.name=name:

}//这是父类

Person.prototype.setAge=function(){};//原型方法

1、类继承(以下使用call)

function Student(){

Person.call(this,"Jack");

}

2、原型式继承

function Student(){}

Student.prototype=new Person();

对比:类继承每次构造函数时继承方法都要创建一遍,函数复用也就无从谈起,另外,超类Person原型中定义的方法对子类Student是不可见的。

而原形式继承本质是克隆而非继承,是把父类所拥有的所有方法和属性克隆一遍给子类,当然,这种一股脑的继承也并不是一定一直都需要的。两种方式各有各的特点

///////////////////////////////////////////////////////////////////////////////

ES5中Object的getPropertypeOf()方法和ES6中的__proto__属性都可以获得对象的原型

原型链的作用是用来实现继承

///////////////////////////////////////////////////////////////////////////////

获取arguments中除第一个元素外的所有其他元素的方法:

var args=Array.prototype.call(arguments,1);

为什么要这么做:1、应用场景是某些时候,第一个参数是作为判定参数或者施效对象,需要获取其他参数参数args;2、由于argument不是数组,无法直接用arguments.slice,于是用call来借用Array的方法

///////////////////////////////////////////////////////////////////////////////

动画中,页面渲染频率,一般浏览器默认的fps(frame per second)应维持在24~60之间。低于24则会卡顿

建议的延时更新dom的时间间隔为16.7(等于屏幕刷新时间)。

setTimeout(fn,0)=>并不是会立即执行,会在主线程中的队列调用完了后再隔大概4ms(不同浏览器不一样)后执行,所以,这里的timer浏览器会认定最小为4

setImmediate(fn)可达到上述效果且几乎不会延迟(可能会有1ms)

setInterval(fn,100)=>下一次fn并不是上一次循环结束后再放入队列中,而是在上一次执行的时候就早已在队列中了。比如:

fn中执行了一个超大的循环(大概要耗费10秒钟运算),那么下一次的fn甚至可能会与上一次的运算同时进行,因为下一次的运算可能会比上一次运算快

///////////////////////////////////////////////////////////////////////////////

gulp本地安装的坑:

1、当前目录必须要有pachage.json

2、npm get global一定要为false,也就是不可以默认为全局安装,否则无法正确安装。(运行install之后输入gulp还是会提示说gulp不是内部命令)

如何做?npm set global=true 将会把默认全局安装设定为true

npm set global=false,却并不会把他改成false

这时候npm config ls查看配置,找到 ;userconfig的值并根据这个路径在文件夹中删除该文件(.npmrc)

这样npm gulp --save-dev就成功了

注意:安装时候有个错误说npm deprecated graceful-fs@3.0.8...之类的话还说什么please update to graceful-fs@^4.0.0 as soon as possible.网上都说可以不必理会,已经安装成功了,一开始我还不信一直以为是这个问题,后来确信了,跟这个真的没关系,不影响使用,根本原因在于万恶的.npmmrc

3、gulp-jshint对jshint有依赖,所以要想使用gulp-jshint,还必须要npm install jshint

///////////////////////////////////////////////////////////////////////////////

UtoVR的使用中,视频一定要是可以获得宽高的视频,否则基于canvas渲染的时候,是没办法进行的

///////////////////////////////////////////////////////////////////////////////

gulp-connect的功能就是在本地启动一个Web Server 

///////////////////////////////////////////////////////////////////////////////

看网上的教程性文档一定要细致,抓住一些关键的点,做到心里有数,在实践的过程中,如果遇到与教程中结果不一致,一定要细致查看教程,看看忽略了那些细节

///////////////////////////////////////////////////////////////////////////////

css clip-path属性可以裁切多边形

兼容语法:

-webkit-clip-path: polygon(0 50%, 50% 0, 100% 50%, 50% 100%);

clip-path: polygon(0 50%, 50% 0, 100% 50%, 50% 100%);

-webkit-clip-path: url("#clip-shape"); 

clip-path: url("#clip-shape");

引用的内敛svg:

<svg width="0" height="0">

    <defs>

        <clipPath id="clip-shape" clipPathUnits="objectBoundingBox">

            <polygon points="0 0.5, 0.5 0, 1 0.5, 0.5 1" />

        </clipPath>

    </defs>

</svg>

其中,clipPathUnits属性的值为objectBoundingBox,这样clipping path就继承了引用了它的HTML元素的边界。

效果:

///////////////////////////////////////////////////////////////////////////////

通过配置package.json快速进行本地node模块安装:

1、pachage.json配置

"devDependencies": {

    "gulp": "^3.9.1",

    "gulp-autoprefixer": "^3.1.0",

    "gulp-cache": "^0.4.5",

    "gulp-concat": "^2.6.0",

    "gulp-dest": "^0.2.3",

    "gulp-if": "^2.0.1",

    "gulp-ignore": "^2.0.1",

    "gulp-imagemin": "^3.0.1",

    "gulp-jshint": "^2.0.1",

    "gulp-less": "^3.1.0",

    "gulp-livereload": "^3.8.1",

    "gulp-minify-css": "^1.2.4",

    "gulp-minify-html": "^1.0.6",

    "gulp-notify": "^2.2.0",

    "gulp-remove-logging": "^1.2.0",

    "gulp-rename": "^1.2.2",

    "gulp-rev": "^7.1.0",

    "gulp-rev-collector": "^1.0.4",

    "gulp-sourcemaps": "^1.6.0",

    "gulp-uglify": "^1.5.3",

    "gulp-useref": "^3.1.0",

    "jshint": "^2.9.2",

    "lazypipe": "^1.0.1"

  }

然后运行 npm install即可一次性安装所有模块依赖

2、npm install gulp del gulp-jshint gulp-uglify即可一次性安装多个插件

///////////////////////////////////////////////////////////////////////////////

关于网页长度单位和font-size:

相对单位:em、%都是相对于父元素的font-size。而rem是相对于html

绝对单位:px、pt。额~其实px相比于pt,也算是相对单位,pt就想cm、m等,是一个物理绝对单位,1pt=1/72inch,而px换算到pt则跟像素密度有关,当屏幕像素密度很大的话,1px对应的视觉物理长度会很小

///////////////////////////////////////////////////////////////////////////////

解决新添加的元素没有事件绑定的方法:

<ul class=“list"><li></li><li></li><li></li></ul>

给li添加点击事件,对于ul中动态添加的li无效,于是可以对ul进行监听

var list=document.getElementsByClassName(“list”)[0];

list.onclick=function(e){

var target=e.target;

if(target.tagName==="li”){

//do something

}

}

我们把li的事件委托给ul.list

这就是大名鼎鼎的事件委托机制

当然jquery中自带事件委托处理的方法,此处不解释,只针对原生js的解决方案进行探讨

但是,这个事件委托机制有个缺陷:当li有子元素的时候,li的子元素点击并不会被生效,因为target不是li。怎么办呢?在li上就是阻止事件的抓捕。如何实现:

用css实现即可:

.list>li>*{pointer-event:none;}

这里是pointer-event的一个应用,这个属性为none的时候表示鼠标在此处变得无效

更多pointer-event的认识和酷炫的应用,看这篇文章吧

http://www.zhangxinxu.com/wordpress/2011/12/css3-pointer-events-none-javascript/

另外,说明一下,并非所有的事件都会冒泡

以下事件天生就不会冒泡:

blur focus mouseenter mouseleave 

另外,以下事件在ie8及以下,并不会参照规范进行冒泡:

change select submit reset

///////////////////////////////////////////////////////////////////////////////

throw new Error(str);//会抛出错误并且停止js的执行

new promise.catch((err)=>console.error(err););//可以将错误信息捕获并输出

///////////////////////////////////////////////////////////////////////////////

console:

console.log(str);//输出

console.info(str);//信息输出

console.warn(str);//警示输出

console.error(str);//错误输出

另外,参数可以有多个,多个参数之间会自动有空格隔开

如console.log(111,222);

输出:111 222

///////////////////////////////////////////////////////////////////////////////

曾经的那个必须用闭包解决的js异步坑,可以用es6的map来快速避开

[1,2,3,4,5].map(id=>setTimeout(()=>console.log(i),100*i););

///////////////////////////////////////////////////////////////////////////////

正则

.*匹配所有非换行字符

[.*\n]匹配所有字符

.*和.*?的区别:前者是贪婪匹配,后者会匹配一次

如:str=STARTabb123e2eeEND要去掉abb和之后第一个e以及他们之间的内容

str.replace(/abb+.*e+/,'');

//output:STARTEnd

str.replace(/abb+.*?e+/,'');

//output:START2eeEnd

///////////////////////////////////////////////////////////////////////////////

node命令跟上>+文件名即可将node输出的内容输出到文件中去

比如:

console.warn(xxxx);

console.log();

///////////////////////////////////////////////////////////////////////////////

node中__dirname是全局变量,可获取当前运行文件路径

///////////////////////////////////////////////////////////////////////////////

清空数组的方法:

arr.splice(0,arr.length);//这样会直接将数组中的内容也清空

然而:arr=[];//这种方法只是将数组指向空,而数组中的项目会残留在内存中等待垃圾回收

虽然两者都有效,但是前者更严谨

///////////////////////////////////////////////////////////////////////////////

编译jade:

方法一:node编译:

1、npm安装jade

2、输入命令:jade xx.jade或者实时监听并编译:jade -p -w xx.jade

方法二:webstorm编译器实时编译:

file=>setting=>tools=>file watchers设置jade,并在arguments一栏中"$FileName$"的前面添加"-P "变成:"-P $FileName$"

///////////////////////////////////////////////////////////////////////////////

node express中,创建的server如何获取客户端传来的参数:

app.get('get',function(req,res){

    var paras=req.query;//客户端传来的所有参数(Object)

    var url=req.url;//客户端访问的url

});

///////////////////////////////////////////////////////////////////////////////

isNaN():

第一步:先将参数转变为数字

第二步:检验是否为数字

即:

isNaN(a)=>

var a=Number(a);

return typeof a==="number";

测试结果如下:

isNaN(0);=>false

isNaN("");=>false

isNaN("12");=>false

isNaN("12a");=>true

isNaN({});=>true

isNaN(undefined);=>true

isNaN(null);=>false

///////////////////////////////////////////////////////////////////////////////

document由

<!doctype html>

<html></html>

这两个元素组成

document.documentElement指html元素

///////////////////////////////////////////////////////////////////////////////

mac中如何配置虚拟主机:

开启apache:sudo apachectl start

用vim打开配置文件:sudo vim /etc/apache2/extra/httpd-vhosts.conf

将如下代码添加到文件中:

<VirtualHost *:8080>

    DocumentRoot "/Users/jun.li/ctb/ctb-project/h5pro"

    ServerName localhost

    DirectoryIndex   index.html index.htm index.php default.index default.php

    ErrorLog "/private/var/log/apache2/sites-error_log"

    CustomLog "/private/var/log/apache2/sites-access_log" common

    <Directory />

    Options Indexes FollowSymLinks MultiViews

    AllowOverride None

    Order deny,allow

    Allow from all

    </Directory>

</VirtualHost>

另外,vim的一些基本命令:

i:进入编辑模式

esc:退出编辑模式

/ServerName(向前查找)

?ServerName(向后查找)

均可以查找字符串ServerName,然后用n(向前)或N(向后)可进行下一个查找

:set ignorecase即可忽略大小写

:set noignorecase对大小写敏感

u撤销之前的修改

:qw写入并且退出

:q!强制退出且忽略之前的更改

///////////////////////////////////////////////////////////////////////////////

通过HTMLElement.prototype添加的原生拓展属性

document.documentElement(即html)以及其子孙元素将会获得,而document和其另外一个子元素——doctype将不会活的

由此可见,html对象源于HTMLElement(这是个function类)

///////////////////////////////////////////////////////////////////////////////

document做委托事件代理监听有个兼容性bug:在部分手机(如iPhone5)上有如下问题

document.addEventListener("click",function(e){

    var tar=e.target;

    ...

});

当tar不为以下元素的时候,事件无法冒泡到document

img、表单元素(label除外)、a标签

也就是说,若目标事件不是上述这些类型的元素,上述的document监听事件无法被触发,其他元素在某些手机(如iPhone5)上的点击监听默认是没有被激活的:

解决办法:

用以下代码激活页面所有的元素的点击监听

document.onclick=function(){return;};

///////////////////////////////////////////////////////////////////////////////

这里通过客户端和服务端中加载本地文件来认识一下二者的区别:

服务端是存放所有文件和资源的地方,当本地要load一个资源的时候,不管这个资源在当前站点所在的服务器还是在其他的服务器上,都需要解析url然后找到制定的目录下去获取相应的资源。也就是说<script src="http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js">还是使用<script src="js/jquery.min.js">,本质上是一样的,所以,很多情况下,这些公用库,完全可以从百度等这些资源库上获取,因为那样加载速度更快,以下是对比百度资源库和微信路况资源库分别加载jquery文件所耗用的时间:

百度资源库(尝试,平均40ms):

微信路况(平均130ms):

当然,此处大小也有差距,前者29.5kb,后者36.3kb

///////////////////////////////////////////////////////////////////////////////

网页编码和语言:

一、html要想中文没问题,必须:

1、文件编码设置为UTF-8

2、meta charset="UTF-8"

二、lang标签含义:

告诉网页你当前标签中的内容所使用的语言(地域),与编码无关,对seo会有影响

传统的值,lang="zh-CN"表示中文,zh-HK粤语,en表示英语,zh-TW表示台湾

新的标准中,lang="zh-cmn-hans-CN"用来代替zh-CN,前缀zh-cmn-hans-代替传统的zh-前缀

///////////////////////////////////////////////////////////////////////////////

以下是资源预加载的顺序和描述

///////////////////////////////////////////////////////////////////////////////

关于项目开发的一些沟通的经验:

1、一旦应用了新的技术方案,一定要记着跟测试说一声,这个地方重点测一下,以免测试借助过往经验认为这个模块已经很成熟了而疏于精细。导致新方案的未知问题出现

2、开发的过程中,永远不要相信自己对逻辑的判断,一定要有事实的真相告诉自己ok,才算通过,比如,一个需要在微信和app上运行的站点,一定要有真实的app环境和微信环境都测验过,才算完成

///////////////////////////////////////////////////////////////////////////////

微信功能链接:

weixin://dl/scan 扫一扫

weixin://dl/feedback 反馈

weixin://dl/moments 朋友圈

weixin://dl/settings 设置

weixin://dl/notifications 消息通知设置

weixin://dl/chat 聊天设置

weixin://dl/general 通用设置

weixin://dl/officialaccounts 公众号

weixin://dl/games 游戏

weixin://dl/help 帮助

weixin://dl/feedback 反馈

weixin://dl/profile 个人信息

weixin://dl/features 功能插件

兼容写法:

不同系统不同浏览器对 url 格式有不同的限制,所以还需要转变一下。

安卓原生浏览器,url地址需要变成 javascript:window.location.href='weixin://dl/favorites';

Chrome 浏览器可以直接用 weixin://dl/favorites

QQ浏览器要用到 data url data:text/html,<html><script>window.location.href='weixin://dl/favorites';</script></html>

上一篇下一篇

猜你喜欢

热点阅读