学习了那么久js,是时候祭出我的js笔记了。
@js单线程
@在 JavaScript 中, 对象 使用 名字作为索引。如果你使用名字作为索引,当访问数组时,JavaScript 会把数组重新定义为标准对象。执行这样操作后,数组的方法及属性将不能再使用,否则会产生错误。
@for...in...循环遍历的实际上是对象的key。所有实例属性都能被遍历到,包括[[enumerable]]=false的。
Object.keys(obj) return可枚举的实例属性的字符串数组
Object.getOwnPropertyNames(obj)return可|不可枚举的实例属性的字符串数组
for...of...循环遍历数组的value。
in 属性在原型或实例中不管可否遍历都return true; Object.hasOwnProperty(obj) 属性在实例中[[enumerable]]return true;
@break label; 多重循环break终于有解决了。<<js高级程序设计三 p58>>
Object.keys(obj).forEach(function(key) {});??
@ null 用于对象, undefined 用于变量,属性和方法。对象只有被定义才有可能为 null,否则为 undefined。so,先使用 typeof 来检测对象是否已定义。
@typeof 返回类型
typeof null -> "object"
typeof [] -> "object"
instanceof 可以判断是否为某类型
@functionName 显示的是整个函数的定义,加()才能调用函数。
@一般各个代码块的作用域都是全局的。
for (var i = 0; i < 10; i++) {}
return i; // i=10;
@函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
@当一个函数作为函数而不是方法来调用的时候,this指向的是全局对象
@数据类型:
number string boolean null undefined object(function特殊的一种object)
@string.split() 字符串转数组。
arr.slice(a,b) 返回arr的a~b项
arr.splice(a,b,val1,val2…) 返回arr在a~b项改为val1,val2,val3…后的数组。功能超多,可实现增删改。
@对象,原型的理解
节省内存用原型。
函数是一种特殊的对象。原型可以理解为工厂生产的模子。
对象分为普通对象和函数对象,Object(),Function()是JS自带的函数对象。
Function()是一个特例,可以理解为函数生产工厂(总工厂),负责生产函数(子工厂)。连Object()也是其生产的。
so,凡是通过 new Function() 创建的对象都是函数对象,其他的(如newf1())都是普通对象。
函数的一个属性就是原型对象prototype(工厂的模子)。注:普通对象没有prototype,但有__proto__属性(指向创建它的函数对象的原型对象prototype(他按照着生产的模子) )。
原型对象其实就是普通对象(Function.prototype除外,它是函数对象,但它很特殊,他没有prototype属性(前面说道函数对象都有prototype属性))
func.prototype就是func的一个实例对象。就是在func创建的时候,创建了一个它的实例对象并赋值给它的prototype
( function f1(){}; ====> var temp= new f1(); f1. prototype = temp; 一个工厂必须要有一个模子 )
func.prototype.__proto__ === Object.prototype
Object.__proto__ === Function.prototype
Function.__proto__ === Function.prototype === Object.__proto__ === GOD
Function.prototype.prototype === Object.__proto__.prototype === undefined
Object.__proto__.__proto__=== Object.prototype
Object. prototype.__proto__ === null ===Object.__proto__.__proto__.__proto__
Object.constructor===Function
对象有”prototype”属性,原型对象有”constructor”属性,用来引用它的函数对象。
原型也是一个对象。每个函数都有一个prototype属性,当一个函数被用作构造函数来创建实例时,这个函数的prototype属性值会被作为原型赋值给所有对象实例(也就是设置实例的`__proto__`属性),也就是说,所有实例的原型引用的是函数的prototype属性。
var c={
name:"shentr",
}
function b() {
}
b.prototype=c;
var a=new b(); // a.__proto__ === b.prototype
console.log(a.__proto__); //{ name: 'shentr' }
console.log(b.__proto__); //[Function]
http://www.108js.com/article/article1/10201.html?id=1092
http://zhangjiahao8961.iteye.com/blog/2070650
@面向对象
工厂模式:在函数内创建一个对象,给对象赋予属性及方法再将对象返回即可
构造函数模式:构造函数的首写字母用大写
原型模式
混合模式
http://www.jb51.net/article/53823.htm
@创建对象
{}
newObject()
Object.create(Object.prototype)
@obj.__proto__ === obj. constructor.prototype ===Object.getPrototypeOf(obj);
@delete obj.a;删除属性,使此属性恢复到原型链上。
obj.a=null;
@obj.hasOwnProperty(proto) 检测属性是实例的还是原型的。
in就不管实例还是原型。
@内建对象:Array() Date() Math()...
宿主对象documentwindow Form Image Element
自定义对象
@new 四步
A.创建一个新对象
B.将构造函数的作用域赋给新对象(所以this就指向了这个新对象)
C.执行构造函数中的代码
D.返回这个新对象
@闭包:在函数A内加个函数B,用B来访问A的局部变量。
var add=function(){ //func A
var counter=0;
return function(){ //func B
return counter+=1;
}
};
var a=add();
/* funcA是funcB的父函数,而funcB被赋给了一个全局变量,这导致funcB始终在内存中,而funcB的存在依赖于funcA,因此funcA也始终在内存中,不会在调用结束后,被垃圾回收机制(garbage collection)回收。*/
/*var a=(function(){
var counter=0;
return function() {
returncounter+=1;
}
})(); //相当于上面的代码,只是用即(自)调用函数简化了一下*/
function myFunction(){
//var a=add(); //此时funcB仍是局部的,调用之后被回收。
document.getElementById("demo").innerHTML=a();
}
http://www.ibm.com/developerworks/cn/web/1207_wangqf_jsthis/this详解
返回函数在调用的时候执行。so,注意返回函数用的变量的值,是调用的时候的值。可以套个即调用函数传参。
1.读取函数内部的变量。
2.让变量的值始终保持在内存中。
jquery的Callbacks()返回self对象就是为了保存list,这个list可给self对象中的键值对共用。
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
https://zhidao.baidu.com/question/586170392.html
访问函数内部的变量不需要return,返回函数内部的变量当然要用return
@借助闭包,可以封装一个私有变量,还可以把多参数的函数变成单参数的函数。
@函数表达式后面可以加括号立即调用该函数,函数声明不可以。 搞出命名空间的特效。 http://www.jb51.net/article/50967.htm
@生成器function*func() {...yield...} 遍历 for(var x offunc()) ,f.next() 优势:保存状态(简化闭包)。简化ajax。@JavaScript的月份范围用整数表示是0~11@RegExp 匹配 /[范围]{个数}/.test('str') 注意/中的\转义/ 切分字符串,用户不规范输入转化成正确数组。 'str'.split(/regexp/)
分组 /(re)(gexp)/.exec('str')
默认贪婪匹配,加? 非贪婪
搜索
@要保证this指向正确,必须用obj.xxx()的形式调用!
@this指向的是内存中真实的对象,与这个对象的名字(引用)无关。
varele1=$("#siz");
varele2=$("#siz");
ele1.out=ele2.out=function(){
log(this);
} //ele1.out()与ele2.out()结果相同
@this 比较懒,只找父级包含层的对象,不会再找父父级包含层对象(直接认window对象为父)。 所以出现that这种hack。 箭头函数完美解决了这个bug。this是函数运行时,自动生成的一个内部对象,只能在函数内部使用, this指的是调用函数的那个对象.
http://www.jb51.net/article/41656.htm
@JavaScript始终将this值作为一个Object,即使它是一个简单的字符串或数字值。
@js能改变html是因为他实现了DOM的接口。
@DOM
@document
@.getElementById .getElementByTagName .getElementByClassName
@.parentNode.children .lastChild.firstChild .nextsibling .previousSibling
@.innerHtml .getAttribute.setAttribute .[attribute] (.src) .style.[property] (.style.color)
.[event] (.onclick) .addEventListener([event],[function],(useCapture))
@.appendChild(document.createElement("p").appendChild(document.createTextNode("新段落。")) )
.cloneChild(true) .cloneNode().hasChildNodes() .insertBefore() .removeChild() .replaceChild()
@.offsetLeft .offsetParent ...
先 加 载 文 档 的 静 态 内 容 , 再 动 态 刷 新 , 动 态 刷 新 不 影 响 文 档 的 静 态 内 容 。 这 正 是 DOM 的 真 正 威 力 : 对 页 面 内 容 进 行 刷 新 却 不 需 要 在 浏 览 器 里 刷 新 页 面 。
@.offsetLeft readOnly不可设值, style.left设值改变css left,但不获取初始值。
getComputedStyle() 只读
@
div.className="ii"; //css类(class)设置为ii,因js中class为保留字,所以名为className
alert(div.getAttribute("class")) //这里用"class"
@dom加载顺序
(1) 解析HTML结构。
(2) 加载外部脚本和样式表文件。
(3) 解析并执行脚本代码。
(4) 构造HTML DOM模型。//ready
(5) 加载图片等外部文件。
(6) 页面加载完毕。//load
@使用节点方法(appendChild等),每次刷新一下页面,所以文档碎片DocumentFragment,
@apply(thisobj,[1,2,3]),call(thisobj,1,2,3) 动态改变this
@回调函数
http://www.jb51.net/article/54750.htm
作为参数,不在出现的地方立即执行,而在需要的时候调用(回调)。
- 异步回调
- 事件触发通知
- 资源加载通知
- 定时器延时
- ajax、动画通知等等。
- 同步回调
长时操作
vartest1=function(callback){
//执行长时间操作
callback();
}
test1(function(){
//执行回调中的方法
});
四种回调
http://www.ruanyifeng.com/blog/2012/12/asynchronous%EF%BC%BFjavascript.html
应用
1.合并相同步骤,回调处理不同。(commonStep为funcA,B,C相同步骤,func1,2,3通过回调处理不同)
2. jQuery.Callbacks()
实现callbacks调用队列
@异步
多个异步都处理完毕后,才能继续下一个动作
http://www.imooc.com/code/3747
Promise
http://www.cnblogs.com/lvdabao/p/es6-promise-1.html
http://www.cnblogs.com/lvdabao/p/5320705.html
http://www.cnblogs.com/lvdabao/p/jquery-deferred.html
@装饰器:给函数增加功能。函数里返回函数。
@Array.sort() 把一切(数字include)转化为string再按ascii码排序,可传入cmp。
@闭包
返回函数在调用的时候执行。so,注意返回函数用的变量的值,是调用的时候的值。可以套个即调用函数传参。
1.读取函数内部的变量,2.让变量的值始终保持在内存中。
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
https://zhidao.baidu.com/question/586170392.html
访问函数内部的变量不需要return,返回函数内部的变量当然要用return
@借助闭包,可以封装一个私有变量,还可以把多参数的函数变成单参数的函数。
varprivFn=function(){
varprivVal; //封装私有变量
returnfunction(){
//实际操作
}
}();
即调函数使privFn重新赋值为return的那个函数,且保留了私有变量privVal.
@函数表达式后面可以加括号立即调用该函数,函数声明不可以。 搞出命名空间的特效。 http://www.jb51.net/article/50967.htm
@生成器function*func() {...yield...} 遍历 for(var x offunc()) ,f.next() 优势:保存状态(简化闭包)。简化ajax。@JavaScript的月份范围用整数表示是0~11
@RegExp 匹配 /[范围]{个数}/.test('str') 注意/中的\转义/ 切分字符串,用户不规范输入转化成正确数组。 'str'.split(/regexp/)
分组 /(re)(gexp)/.exec('str')
默认贪婪匹配,加? 非贪婪
搜索
@6种类型:number、string、boolean、function、undefined、object
@JSON的字符串规定必须用双引号,Object的键也必须用双引号。
@
每个对象(除null)都有原型。
@exec
if 未分组 : return第一个匹配元素,else:return所有匹配的分组
@ 目标节点是已存在并且有一部分内容的情况下,使用createDocumentFragment可避免因createElement多次添加到document.body引起的效率问题。
@作用域只体现在函数,对象上,不体现在循环上。
@滚动条
window.onscroll()
document.documentElement.scrollTop ///一般为0,整个documentscroll位置
document.body.scrollTop ///scroll位置
@预编译 JS解析器在执行语句前会将函数声明和变量定义进行"预编译",而这个"预编译",并非一个页面一个页面地"预编译",而是一段一段地预编译,所谓的段就是一个<script> 块。
@js粒度小,灵活,但表现力是硬伤
@stopPropagation在事件函数中
oB.onclick = function(e){
e.stopPropagation(); ///取消冒泡
alert('b');
};
@Event
returnfalse; 仅仅是在HTML事件属性 和 DOM0级事件处理方法中 才能通过返回 returnfalse 的形式组织事件宿主的默认行为。DOM的事件传播有两个类型,一个是捕获(从父节点到子节点),一个是冒泡(从子节点到父节点),所以一个事件触发时可以有多个处理器去处理它,DOM标准约定了returnfalse后就会阻止事件继续传播。
@margin是有默认值滴。。http://www.jb51.net/web/78118.html
@Javascript 中的 undefined并不是作为关键字,因此ie8可以允许用户对其赋值。
@纯匿名函数(不赋值,不执行)在语法上是错误的。
四种上下文调用方式:方法调用模式、函数调用模式、构造器调用模式、apply调用模式:
@内存泄漏
- 含有DOM对象的循环引用将导致大部分当前主流浏览器内存泄露
循环引用:
第一种:多个对象循环引用
vara=new Object;
varb=new Object;
a.r=b;
b.r=a;
第二种:循环引用自己
vara=new Object;
a.r=a;
循环引用很常见且大部分情况下是无害的,但当参与循环引用的对象中有DOM对象或者ActiveX对象时(new Object变document.getElementById等),循环引用将导致内存泄露。
@touch事件
touchstart,touchmove,touchend,
mouse事件
mousedown,mouseup,mousemove,mouseclick
@类型判断
Array.isArray(); //ie9+
function isArray(value){
returnObject.prototype.toString.call(value) === '[object Array]'
} //其他同理
@encodeURI() 不对属于URI本身的字符编码(更常用)
encodeURIComponent() 所有非字母数字编码
@eval() 字符串解析成js语句并运行。用户输入不能用此(代码注入)
@书
https://www.zhihu.com/question/19562698
------------------------------------------------------------------------------------Hacks----------------------------------------------------------------------------------
@ IE6、IE7对直接附加在 DOM Element 上的对象的垃圾回收存在问题. http://www.imooc.com/code/4309
@dom
http://www.imooc.com/code/4571
@querySelectorAll 即使提供一个上下文范围,但浏览器无视了这个上下文。
@innerHTML接口高效,but
IE会对用户字符串进行trimLeft操作,用户可能的本意就是需要空白
IE8有些元素innerHTML是只读
IE会忽略开头的无作用域元素
大多情况下不执行script脚本,当然如果支持defer的IE9之前的浏览器除外
一些标签不能作为div的子元素,如tr,tb,col等
@mvc,mvp,mvvm
http://www.ruanyifeng.com/blog/2015/02/mvcmvp_mvvm.html
@ var target = e.target || window.event.srcElement;
@只读属性
Object.defineProperty(a,'name',{
writable:false,
value:2
})
@var a={a:1,b:3};var b=a; a=null;
a=null;只是把a的栈内存清空,堆内存因为仍被引用不被清空,所以b不变。