知识点总结:
- 带 var 在变量提升阶段只声明不定义; 带 function 声明且定义
- 如果函数执行没有返回结果,则返回
undefined
console.log(a, b, c); // undefined*3
var a = 12,
b = 13,
c = 14;
function fn(a) {
console.log(a, b, c); // 10 13 14
a = 100; // => 此处修改的是私有变量(形参赋值下的a)
c = 200;
console.log(a, b, c); // 100 13 200
}
b = fn(10);
console.log(a, b, c); // 12 undefined 200
知识点总结:函数作用域是创建时候的执行上下文
var i = 0;
function A() {
var i = 10;
function x() {
console.log(i);
}
return x;
}
var y = A();
y(); // 10
function B() {
var i = 20;
y();
}
B(); // 10
var a=1;
var obj ={
"name":"tom"
}
function fn(){
var a2 = a;
obj2 = obj;
a2 =a;
obj2.name =”jack”;
}
fn();
console.log(a); // 1
console.log(obj); // {"name":"jack"}
var a = 1;
function fn(a){
console.log(a)
var a = 2;
function a(){}
}
fn(a); // ƒ a(){}
console.log(a); // undefined
var a=12;
function fn(){
console.log(a); // undefined
var a=13;
}
fn();
console.log(a);//12
console.log(a); // undefined
var a=12;
function fn(){
console.log(a); // 12
a=13;
}
fn();
console.log(a); // 13
console.log(a); // 报错: a is not defined
a=12;
function fn(){
console.log(a);
a=13;
}
fn();
console.log(a);
-
- 自执行函数:创建(堆)+执行(私有上下文)一并完成
-
- 逻辑或和逻辑与表达式
- A||B:验证A是真还是假(只有 0/NaN/null/undefined/空字符串 是假),如果A是真,返回的A的值,如果A是假,返回B的值(不论B的值是啥)
- A&&B:A是真返回B的值,A是假返回A的值
- 同时出现的时候,&&优先级高于 ||
var foo='hello';
(function(foo){
console.log(foo);
var foo=foo||'world';
console.log(foo);
})(foo);
console.log(foo);
延伸 ES6中默认传参的另外一种表达
function func(x, y, z = 0) {
// z = 0 ES6设置默认值的方式(不传递值,赋值默认值)
}
function func(x, y, z) {
/* if (typeof z === "undefined") {
z = 0;
} */
z = z || 0;
//这样也可以,只不过不如上面的准确,上面都是不传递赋值默认值,这样写是不传或者传递的值是假,都会赋值默认值【不严谨,但是很多人都在这样用】
}
func(10, 20);
function func(callback) {
/* if (typeof callback === "function") {
callback();
} */
callback && callback(); //【依然不严谨,一般我们默认要不就不传,传递一定是函数】
}
func(function anonymous() {});
自执行函数本身应该是匿名函数(还有函数表达式或者回调函数等都是匿名函数),只不过为了保证良好编码习惯,我们经常给本应是匿名的函数 “具名化”(起个名字)
- 1.这个名字只能在函数内部被调用,函数外面用不了(可以理解为是私有变量)
- 2.这个名字的变量,在函数内部,值也是不能被修改的(改了也没用,还是代表函数)
var b = 10;
(function b() {
b = 20;
console.log(b); // 函数本身
})();
console.log(b); // 10
延伸1:取代严格模式下不支持的arguments.callee
(function AAA() {
// console.log(AAA); //=>函数本身(这样后期在递归调用的时候,可以直接基于AAA执行即可,无需再使用arguments.callee了【arguments.callee在严格模式下不支持】)
AAA = 1000;
console.log(AAA); //=>函数本身
})();
console.log(AAA); //=>Uncaught ReferenceError: AAA is not defined
延伸2: 如果是基于VAR/LET/FUNCTION等操作单独处理,会把这个具名化的名字改为正常的私有变量,也就是名字不再代表函数了
(function AAA() {
/*
* 如果是基于VAR/LET/FUNCTION等操作单独处理,会把这个具名化的名字改为正常的私有变量,也就是名字不再代表函数了
*/
// console.log(AAA); //=>Uncaught ReferenceError: Cannot access 'AAA' before initialization
let AAA = 100;
console.log(AAA); //=>100
})();
(function AAA() {
console.log(AAA); //=>函数(输出1的)
function AAA(){console.log(1)}
console.log(AAA); //=>函数(输出1的)
})();
(function AAA() {
console.log(AAA); //=>undefined
var AAA = 200;
console.log(AAA); //=>200
})();