##转载
一、函数定义的三种方式
方式1、函数声明
function foo(){}
方式2、函数表达式
var foo = function(){};
方式3、构造函数
var foo=new Function("alert('xiaoxiao')");
注意:申明提前的问题
变量和函数都有申明提前的概念,但是赋值还是在实际地方复制的。所以使用方式2的时候特别要注意了。
用方式1声明函数并使用:
foo(); // 正常运行,因为foo在代码运行前已经被创建
function foo() {}
用方式2声明函数并使用:
foo; // 'undefined'
foo(); // 出错:TypeError
var foo = function() {};//因为变量的赋值操作使用时在这里才完成
备注:表达式函数声明,需要在他后面才可调用此函数。
二、this的工作原理
this指针永远是这个引用所属的对象。
参考资料: http://blog.chinaunix.net/uid-15223977-id-2774361.html
三、闭包
javascript规定,当前作用域总是能够访问外部作用域的变量。当我们需要在外部访问私有变量的时候就不可能了。只有通过闭包来实现这个功能。
function Counter(start) {
var count = start;
return {
increment: function() {
count++;
},
get: function() {
return count;
}
}
}
var foo = Counter(4);
foo.increment();
foo.get(); // 5
foo.get()能够输出5,是应为返回的两个闭包increment和get保持了维持着对外部作用域Counter的引用,所以总能够访问到这个作用域内定义的变量count
循环中的闭包问题
在实际开发中最容易出问题的是在循环中使用闭包
for(var i = 0; i < 10; i++) {
setTimeout(function() {
console.log(i);
}, 1000);
}
这里我们期望输出的是0到9的数字,但是实际输出的是10次10.
当console.log被调用的时候,匿名函数保持了对外部变量i的引用,此时for循环已经结束,i的值已经是10了。
解决办法:每次循环中创建变量i的拷贝,setTimeout外部的匿名函数会立即执行,并且把i作为它的参数,此时函数内e变量就拥有了i的一个拷贝。
for(var i = 0; i < 10; i++) {
(function(e){
setTimeout(function() {
console.log(e);
}, 1000);
})(i);
}
四、构造函数
JavaScript 中的构造函数和其它语言中的构造函数是不同的。 通过 new 关键字方式调用的函数都被认为是构造函数。
在构造函数内部 - 也就是被调用的函数内 - this 指向新创建的对象 Object。 这个新创建的对象的 prototype 被指向到构造函数的 prototype。
五、作用域和命名空间
作用域
javascript的作用域并不是其他语言中的花括号代码段,它并不支持块级作用域;而是函数作用域。
ES6提出的新的操作(let关键字)可以支持块级作用域。
var a = 5;
if(true){
var a = 10;
}
console.log(a);//10
使用let关键字
let a = 5;
if(true){
let a = 10;
}
console.log(a); //5
命名空间
只有一个全局作用域导致的常见错误是命名冲突。在 JavaScript中,这可以通过 匿名包装器 轻松解决。
(function() {
// 函数创建一个命名空间
window.foo = function() {
// 对外公开的函数,创建了闭包
};
})(); // 立即执行此匿名函数
最新访客: