##js的拖拽javascript
在拖拽时容易使操做变成选择文本,这时应该添加这段:html
$("#ul").on("selectstart", "li", function(e){ this.dragDrop && this.dragDrop(); return false; });
##js的event对象前端
先看文章的代码:java
//获取event对象 //标准DOM方法事件处理函数第一个参数是event对象 //IE可使用全局变量window.event var evt = window.event?window.event:e; //获取触发事件的原始事件源 //标准DOM方法是用target获取当前事件源 //IE使用evt.srcElement获取事件源 var target = evt.target||evt.srcElement; //获取当前正在处理的事件源 //标准DOM方法是用currentTarget获取当前事件源 //IE中的this指向当前处理的事件源 var currentTarget= e?e.currentTarget:this; //问题:在IE 9下 window.event 与 e 不一样 evt没有currentTarget属性,e才有currentTarget属性(视为标准浏览器作法??) alert("src id:"+target.id+"\ncurent target id :"+currentTarget.id);
currentTarget:事件冒泡阶段所在的DOM。在捕获事件时,这个currentTarget就为监听事件的那个DOM元素,当事件结束时,currentTarget为nulljquery
target, originalTarget, srcElement:触发事件原始的DOMgit
##jQuery.ready, DOMContentLoaded, window.onload区别github
先看jQuery.ready,查看jquery-1.11.3.js
源代码:ajax
// Catch cases where $(document).ready() is called after the browser event has already occurred. // we once tried to use readyState "interactive" here, but it caused issues like the one // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 if ( document.readyState === "complete" ) { // Handle it asynchronously to allow scripts the opportunity to delay ready setTimeout( jQuery.ready ); // Standards-based browsers support DOMContentLoaded } else if ( document.addEventListener ) { // Use the handy event callback document.addEventListener( "DOMContentLoaded", completed, false ); // A fallback to window.onload, that will always work window.addEventListener( "load", completed, false ); // If IE event model is used } else { // Ensure firing before onload, maybe late but safe also for iframes document.attachEvent( "onreadystatechange", completed ); // A fallback to window.onload, that will always work window.attachEvent( "onload", completed ); ......
可看出jQuery也是主要利用DOMContentLoaded事件编程
DOMContentLoaded是在DOM结构绘制完毕后就执行,不必定要等全部的js和图片加载完毕,就能够执行一些方法json
window.onload则必须等到页面内包括图片(图片也加载完成,img.complete===true时)的全部元素加载完毕后才能执行
##javascript三种设置访问器属性的方式
详情:http://avalonjs.github.io/#tutorial/concepts/vmodel.html
另外一小小的知识点:普通类型变量给它定义属性没用
##针对retina的支持
// 优化retina, 在retina下这个值是2 var ratio = window.devicePixelRatio || 1;
##判断图片是否已加载了
利用complete
属性可判断:img.complete
##运算符的优先级
##visibilitychange事件
标签页激活检测(视觉改变触发):当用户焦点在另一个标签上,或从新回到标签时,触发visibilitychange
事件:
$(document).on('visibilitychange', function (e) { if (e.target.visibilityState === "visible") { console.log('Tab is now in view!'); } else if (e.target.visibilityState === "hidden") { console.log('Tab is now hidden!'); } });
##cookies,sessionStorage和localStorage的区别
x = 1 function bar(){ this.x = 2 return x } var foo = new bar() alert(foo.x) // -> 2
这里主要问题是最外面x的定义,试试把x=1改为x={},结果会不一样的。这是为何呢?
在把函数看成构造器使用的时候,若是手动返回了一个值,要看这个值是否简单类型,若是是,等同于不写返回,若是不是简单类型,获得的就是手动返回的值。若是,不手动写返回值,就会默认从原型建立一个对象用于返回。
##js的script标签的defer和async属性
[defer]
能够在<script>
中加入defer
属性,告诉浏览器这段script没必要当即执行,那么浏览器就会在彻底载入文档以后再执行这个script,至关于window.onload
,但它比window.onload
更灵活。
<script defer="true"></script>
[async]
使用async
属性加载JavaScript,这样整个脚本就能够异步加载和执行。
<script>
标签的defer属性——告诉浏览器该脚本不会在页面加载完成以前操做DOM,脚本将会和其余资源文件并行下载; <script>
标签的async属性——HTML5新的异步、并行模式,脚本将在完成下载后等待合适的时机执行代码。
##parseInt,parseFloat
parseInt('0xA') // return 10` parseInt('A') // return NaN` parseInt('A', 16) // return 10` parseFloat('22.22.22') // return 22.22` parseFloat('A', 16) // return NaN`,没有基模式 parseFloat('0xA') // return 0`,不转换为十六进制,直接转前面数字部分而已
void
运算符对任何值都返回undefined
,该运算符经常使用于避免输出不该该输出的值。例如: <a href="javascript:window.open('about:blank');">Click Me</a>
其中,window.open()
返回对新打开窗口的引用,会输出字符串的,应该改成: <a href="javascript:void(window.open('about:blank'));">Click Me</a>
==
false == 0 -> true false == "0" -> true null == 0 -> false +null === 0 -> true null <= 0 -> true null < 1 -> true '' == 0 -> true // ''会被转换为数字, 至关于+'' == 0 '' == false -> true [] == false -> true [] == '' -> true true == 1 -> true true == 2 -> false '5' == 5 -> true isNaN('123') -> false isNaN(null) -> false Number([]) === Number('') === 0
小结:null 只弱等于 undefined , 但Number(null)等于0,0跟false是弱等的,因此 null != false, +null == false
使用scriptCharset
便可解决问题,用contentType
就不必定能够了。
$.ajax({ url: testUrl, dataType: 'jsonp', type: 'post', scriptCharset: 'utf-8' });
##URL的基本概念:URL完整组成部分
纠正一下:
path
参数不包括hash
window.location
不包括path属性,只有pathname##window.onload和DOMContentLoaded事件的区别
前者是DOM,图片,样式表,flash等加载完成后触发的,后者是DOM加载完成,但样式表和图片可能未加载完成时就触发的,而且只在某些浏览器中有此事件。
##JavaScript的原型
JavaScript是基于原型的编程语言,当你读取一个对象的属性,JavaScript首先会在本地对象中查找这个属性,若是没找到,JavaScript开始在对象的原型中查找,若仍未找到,还会继续查找原型的原型,直到查找到Object.prototype。若是找到这个属性,则返回这个值,不然返回undefined. 换句话说,若是你给Array.prototype添加了属性,那么全部JavaScript数组都具备了这个属性
##变量提高
变量提高指的是,不管是哪里的变量,都是在一个范围内声明的。JavaScript引擎会将这个声明移到范围的顶部。如:
function foo(){ // 此处省略若干代码 var a = 100; }
运行代码时,实质就是这样:
function foo(){ var a; // 此处省略若干代码 a = 100; }
##hasOwnProperty ##isPrototypeOf ##constructor
hasOwnProperty
检查该对象是否有属于它自己的属性/对象,而不是它原型上的属性/对象。由于毕竟那是它原型的属性,而不是它本身的。就等于你能够花你老爸的钱,但毕竟不是你的钱。如:
isPrototypeOf
顾名思义,检查该对象是否为另一对象的原型
constructor
对建立对象的函数的引用(指针),指向的老是一个function
prototype
对该对象原型的引用,返回的是一个object实例
var Foo = function(){ this.age = 25; }; Foo.prototype.count = 100; Foo.prototype.get = function(){return this.count;}; var f = new Foo(); console.log("age",f.hasOwnProperty("age")); // age true console.log("count",f.hasOwnProperty("count")); // count false console.log(Foo.prototype.hasOwnProperty("count")); // true console.log(Foo.prototype.hasOwnProperty("get")); // true f.age // -> 25 f.count // -> 100,虽然不是f的ownProperty,但直接读取该属性也是能够的 console.log(Foo.prototype.isPrototypeOf(f)); // -> true console.log(Foo === f.constructor); // -> true
##关于__proto__和prototype的区别
最简单来讲,__proto__属性是实例对象的原型属性,prototype是构造函数的原型属性,二者应该是相等的。如:
function B(){this.name = 'kobe';} B.prototype.age = 20; var b = new B(); alert(b.__proto__ === B.prototype); // true
当使用new关键字来调用构造函数时,若是构造函数里没有返回任何内容,就会返回this——当前上下文的对象,要否则就返回任意非原始类型的值,如数组,object。如:
var Class1 = function(){return {};}, Class2 = function(){return [];}, Class3 = function(){return function(){};}, Class4 = function(){return 123;}, Person1 = new Class1, // {} Person2 = new Class2, // [] Person3 = new Class3, // function(){} Person4 = new Class4; // function instanceof Class4
##栈stack和堆heap的区别
原始值是存储在栈中的简单数据段,也就是说,它们的值直接存储在变量访问的位置;引用值是存储在堆中的对象,也就是说,存储在变量处的值是一个指针,指向存储对象的内存处。若是一个值是引用类型的,那么它的存储空间将从堆中分配。因为引用值的大小会改变,因此不能把它放在栈中,不然会下降变量查寻的速度。相反,放在变量的栈空间中的值是该对象存储在堆中的地址。地址的大小是固定的,因此把它存储在栈中对变量性能无任何负面影响。
##Number值集合的外边界:Number.MAX_VALUE和Number.MIN_VALUE
全部ECMAScript数都必须在这两个值之间,不过计算生成的数值结果能够不落在这两个数之间。当计算生成的数大于Number.MAX_VALUE时,它将被赋予值Number.POSITIVE_INFINITY,意味着再也不有数字值,一样,生成的数值小于Number.MIN_VALUE的计算也会被赋予值Number.NEGATIVE_INFINITY,也再也不有数字值。若是返回的是无穷大值,那么结果就不能再用在其余计算。
无穷大的值:Infinity === Number.POSITIVE_INFINITY
,-Infinity === Number.NEGATIVE_INFINITY
,判断是否有穷的isFinite(123) === true
##数字转换为二进制字符串
a=12345, a.toString(2) === "11000000111001"
,与之相对的是 a = parseInt("11000000111001", 2) === 12345
##闭包(closure) ##做用域链
做用域链:js只有函数做用域和全局做用域。做用域链就是从内部函数做用域到外部函数做用域,一直到全局做用域。闭包是简单来讲是函数中使用函数,内部函数使用到外部函数的变量,而外部函数以外的做用域对外部函数的返回值有引用,那么外部函数就成了一个闭包,内部函数对外部函数的引用链就不会销毁。
闭包意味着内层的函数能够引用存在于包围它的函数内的变量,即便外层函数的执行已经终止
闭包主要的应用场景以及一些特色有:
var obj = (function(){ var privateVar; return { get: function(){ return privateVar; }, set: function(value){ privateVar = value } }; })();
(function($, undefined){/*…*/})(jQuery)
但闭包有在for/next循环中使用闭包却不声明变量来保存迭代变量当前值的一些风险。闭包容许你引用父函数中的变量,但提供的值并不是该变量建立时的值,而是在父函数范围内的最终值。
在函数A内定义一个函数B,B对A中的一些变量有引用,那么A即便运行结束,B对A变量的引用链也不会销毁。因此闭包不能滥用!
##垃圾回收机制 ##循环引用
在函数中声明一个变量,则将其标记为「进入环境」,当变量离开环境时,则将其标记为“离开环境”。
垃圾回收器在运行的时候会给存储在内存中的全部变量都加上标记(固然,可使用任何标记方式)。而后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记(闭包)。而后销毁那些带标记的值并回收它们所占用的内存空间
引用计数的含义是跟踪记录每一个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。若是同一个值又被赋给另外一个变量,则该值的引用次数加1。相反,若是包含对这个值引用的变量又取得了另一个值,则这个值的引用次数减1。当这个值的引用次数变成0时,则说明没有办法再访问这个值了,于是就能够将其占用的内存空间回收回来。这样,当垃圾回收器下次再运行时,它就会释放那些引用次数为0的值所占用的内存。
Netscape Navigator3是最先使用引用计数策略的浏览器,但很快它就遇到一个严重的问题:循环引用。循环引用指的是对象A中包含一个指向对象B的指针,而对象B中也包含一个指向对象A的引用。
function fn() { var a = {}; var b = {}; a.pro = b; b.pro = a; } fn();
以上代码a和b的引用次数都是2,fn()执行完毕后,两个对象都已经离开环境,在标记清除方式下是没有问题的,可是在引用计数策略下,由于a和b的引用次数不为0,因此不会被垃圾回收器回收内存,若是fn函数被大量调用,就会形成内存泄露。
咱们知道,IE中有一部分对象并非原生js对象。例如,其DOM和BOM中的对象就是使用C++以COM对象的形式实现的,而COM对象的垃圾回收机制采用的就是引用计数策略。所以,即便IE的js引擎采用标记清除策略来实现,但js访问的COM对象依然是基于引用计数策略的。换句话说,只要在IE中涉及COM对象,就会存在循环引用的问题。
因此,有时需手动切断JS对象与DOM的链接:
$dom._object = null; jsObj._dom = null;