http://bonsaiden.github.io/JavaScript-Garden/zh/
* js的定义是提前的,但赋值不是提前的
var foo = 10function calc () {
// body...
alert(foo);
var foo = 2;
}
calc();
输出为undefined 变量分为局部和全局 第一个foo为全局,calc中的为局部(函数内没有var也为全局),
该函数类似于:
var foo;
alert(foo);
foo = 2; // 提前声明
1.充分理解 原型链继承 的工作方式
2.for in 遍历属性 + hasOwnProperty函数--> 排除原型链上的属性
3.函数
闭包 // 闭包就是能够读取其他函数内部变量的函数,定义在函数内部的一个函数,连接函数内部和函数外部的桥梁
a.把匿名函数作为回调函数传递到异步函数中
1.函数声明: function foo() {}
2.函数赋值表达式 var foo = function(){} // 把一个匿名函数赋值给变量foo
3.命名函数赋值给表达式
var foo = function bar(){
bar(); // normal,这样是有问题的,当你调用了foo后,执行bar,这样就会循环调用bar
}
bar(); // ReferenceError 对外不可见
4.this
a.全局this 在全局范围内使用this ,则指向全局对象
b.函数调用 foo(); 这是调用全局函数,所以this也是全局对象
c.方法调用 test.foo() this 指向test对象
d.构造函数 new Foo() this指向新建的对象
e.显示设置this
function foo(a,b) {}
var bar = {};
foo.apply(bar,[1,2])
foo.call(bar,1,2)
调用apply或者call的第一个参数为this
f.内部函数作为回调等使用外部函数的this, 可以用bind(this,params) 或者
function(){
var that = this;
function test(){
that // 内部函数可以访问外部函数的参数
}
#######################################################
5.闭包和引用
a.模拟私有变量 <返回两个闭包>
function Counter (start) {
// body...
var count = start;
return {
increment: function () {
// body...
count ++;
},
get:function () {
// body...
return count;
}
}
}
var foo = Counter(4); // !!!
foo.increment();
foo.get(); // 5
b.循环中的闭包 <常见错误>
for (var i = 0; i < 10; i++) {
setTimeout(function(){
console.log(i);
},1000)
}
上述代码不会输出0~9 而是输出10 十次,当console.log被调用的时候。匿名函数保持对外部的变量i的引用
此时for已经结束,i为10. 为了得到想要的结果,要创建变量拷贝i
c.匿名包裹器 <自执行匿名函数>
for (var i = 0; i < 10; i++) {
(function(e){
setTimeout(function () {
// body...
console.log(e);
},1000)
})(i);
}
////or////////
for(var i = 0; i < 10; i++) {
setTimeout((function(e) {
return function() {
console.log(e); // 返回一个函数
}
})(i), 1000)
}
6.arguments
每个函数内部都能访问的一个特别变量 传递进来的参数列表,有length属性但不是数组,可以修改
7.构造函数
使用 new 如果没有显示的return 会返回 当前新建对象 this
8.工厂模式
9.作用域与命名空间
return 的内容不在同一行会报错
例子1 作用域
var myVar = "var"
(function func () {
// body...
alert(myVar);
var myVar = "vv"; // 定义会提到当前作用域顶部,但是不会赋值
})() // 匿名函数包裹器
// undefined
例子2 命名空间
通过匿名函数包裹器
(function(){
window.Events = {}
window.Events.addCustomEvent = function (eventType) {
// body...
}
})()
--> 另外两种匿名函数包装器方式
+function(){}()
(function(){}())
数组
1.不用for in 而是用for。 因为for in会访问原型链上的属性,配合hasOwnProperty对{}使用
var list = [1,2,3,4,....1000];
for (var i = 0,len = list.length; i < list; i++) {
};
上面函数有个处理[长度缓存],len = list.length , 因为在每次循环时去范围后还是有性能开销
2.length setter,getter 截断数组和获取长度
3.创建数组 [],而不要用new Array...
4.== 和 === 推荐使用 ===
在比较之前,自己先显示转换类型,而不是用语言本身的强制转换规则
typeof操作符
1.typeof操作符 和instanceof获取是js中最大的设计缺陷,几乎不可能得到想要的结果
2.比较
var str = "str";
console.log(typeof(str)); // string
console.log(str.constructor.name); // String
---------------------------------------------------
Value Class Type
-------------------------------------
"foo" String string
new String("foo") String object
1.2 Number number
new Number(1.2) Number object
true Boolean boolean
new Boolean(true) Boolean object
new Date() Date object
new Error() Error object
[1,2,3] Array object
new Array(1, 2, 3) Array object
new Function("") Function function
/abc/g RegExp object (function in Nitro/V8)
new RegExp("meow") RegExp object (function in Nitro/V8)
{} Object object
new Object() Object object
!! 除非为了检测一个变量是否定义过 未定义:undefined,否则应避免使用typeof操作符
instanceof : 比较两个操作数的构造函数。 只有在处理自定义类型时才有意义。 否则想typeof一样,多种情况都放回object
function Aoo(){}
function Foo(){}
Foo.prototype = new Aoo();
var foo = new Foo();
console.log(foo instanceof Aoo);
var cls1 = a.constructor.name
var cls2 = Object.prototype.toString.call(a).slice(8,-1)// 推荐
function is(type, obj){
var clas = Object.prototype.call(obj).slice(8,-1);
return obj !== undefined && obj !== null && clas === type
}
与typeof一样,比较同一个javascript上写文的自定义对象以外,慎用
undefined
undefined 是一个值为 undefined的类型,她是一个全局变量
下面情况会返回undefined
访问未修改的全局变量undefined //
没有定义 return 的函数的返回值
return 没有显示的内容
访问不存在的属性
函数参数没被显示的传递值
任何被设置为 undefined 值的变量
setTimeout setInterval
setTimeout(func,1000) // 在1秒后调用func, 如果想多次调用,在func中调用setTimeout 或者使用setInterval
setTimeout 用法,setTimeout(回调函数, 时间, 参数1, ..., 参数n)。
setInterval(func,1000)// 每1秒调用func,不会停止调用,除非调用clearInterval() 参数为id号[setInterval调用时会返回]