开发app和网站建设那个好些,怎么给网站做备份呢,中国最强十大国企,小说网站上的广告在哪做JavaScript高级程序设计(第4版)读书分享笔记记录 适用于刚入门前端的同志 定义函数 定义函数有两种方式#xff1a;函数声明和函数表达式大致看这两种方式没有什么区别#xff0c;事实上#xff0c;JavaScript 引擎在加载数据时对它们是区别对待的。JavaScript 引擎在任何代… JavaScript高级程序设计(第4版)读书分享笔记记录 适用于刚入门前端的同志 定义函数
定义函数有两种方式函数声明和函数表达式大致看这两种方式没有什么区别事实上JavaScript 引擎在加载数据时对它们是区别对待的。JavaScript 引擎在任何代码执行之前会先读取函数声明并在执行上下文中生成函数定义。而函数表达式必须等到代码执行到它那一行才会在执行上下文中生成函数定义。 函数声明式
栗子
function sum (num1, num2) { return num1 num2;
} 函数提升
栗子
console.log(sum(10, 10)); //20
function sum(num1, num2) { return num1 num2;
} 以上代码可以正常运行因为函数声明会在任何代码执行之前先被读取并添加到执行上下文函数声明提升。执行原理在执行代码时JavaScript 引擎会先执行一遍扫描 把发现的函数声明提升到源代码树的顶部。因此即使函数定义出现在调用它们的代码之后引擎也会把函数声明提升到顶部 注意如果把前面代码中的函数声明改为等价的函数表达式那么执行的时候就会出错。 栗子 // 会出错
console.log(sum(10, 10)); // // Error! function doesnt exist yet
let sum function(num1, num2) { return num1 num2;
}; 函数表达式 函数表达式看起来就像一个普通的变量定义和赋值即创建一个函数再把它赋值给一个变量. 这样创建的函数叫作匿名函数anonymous funtion因为 function 关键字后面没有标识符 栗子 let functionName function(arg0, arg1, arg2) { // 函数体
};
// or
let functionName;
functionName function(arg0, arg1, arg2) { // 函数体
}; 箭头函数 ECMAScript 6 新增了使用胖箭头语法定义函数表达式的能力。 很大程度上箭头函数实例 化的函数对象与正式的函数表达式创建的函数对象行为是相同的。任何可以使用函数表达式的地方都可以使用箭头函数 栗子 let arrowSum (a, b) { return a b;
};
console.log(arrowSum(5, 8)); // 13 如果只有一个参数那也可以不用括号。只有没有参数或者多个参数的情况下才需要使用括号。 注意 箭头函数虽然语法简洁但也有很多场合不适用。箭头函数不能使用 arguments、super 和 new.target也不能用作构造函数。此外箭头函数也没有 prototype 属性。 理解参数 读取函数参数可以用到命名参数和arguments对象。 arguments 对象是一个类数组对象因此可以使用中括号语法访问其中的 元素第一个参数是 arguments[0]。而要确定传进来多少个参数可以访问arguments.length 属性。 栗子 function sayHi(name, message) { console.log(Hello name , message); console.log(arguments.length);
}//等价于function sayHi() { console.log(Hello arguments[0] , arguments[1]); console.log(arguments.length);
}sayHi(Tom,welcome To My CSDN); // 2 还有一个必须理解的重要方面那就是 arguments 对象可以跟命名参数一起使用。 栗子 function doAdd(num1, num2) { if (arguments.length 1) { console.log(num1 10); } else if (arguments.length 2) { console.log(arguments[0] num2); }
} arguments arguments 对象其实还有一个 callee 属性是一个指向 arguments 对象所在函数的指针。 使用 arguments.callee 就可以让函数逻辑与函数名解耦 使用栗子 function factorial(num) { if (num 1) { return 1; } else { return num * factorial(num - 1); }
}//等价于
function factorial(num) { if (num 1) { return 1; } else { return num * arguments.callee(num - 1); //arguments.callee代表factorial}
} 箭头函数中的参数 上面提到过箭头函数如果函数是使用箭头语法定义的那么传给函数的参数将不能使用 arguments 关键字访问而只能通过定义的命名参数访问。 默认参数值 ECMAScript 6 支持显式定义默认参数了。 栗子 function makeKing(name Henry) { return King ${name} VIII;
}
console.log(makeKing(Louis)); // King Louis VIII
console.log(makeKing()); // King Henry VIII//箭头函数也可let makeKing (name Henry) King ${name};
console.log(makeKing()); // King Henry 扩展参数 在 ECMAScript 6 中可以通过扩展操作符极为简洁地实现参数扩展。 因为数组的长度已知所以在使用扩展操作符传参的时候并不妨碍在其前面或后面再传其他的值 包括使用扩展操作符传其他参数普通传参可以和扩展传参一起使用 栗子 let values [1, 2, 3, 4];
function getSum() { let sum 0; for (let i 0; i arguments.length; i) { sum arguments[i]; } return sum;
}console.log(getSum(...values)); // 10//等价于 getSum(1,2,3,4)console.log(getSum(-1, ...values)); // 9
//等价于 getSum(-1,1,2,3,4)
console.log(getSum(...values, 5)); // 15
console.log(getSum(-1, ...values, 5)); // 14
console.log(getSum(...values, ...[5,6,7])); // 28
//等价于 getSum(1,2,3,4,5,6,7) 函数内部 this this它在标准函数和箭头函数中有不同的行为。(重点) 在标准函数中this 引用的是把函数当成方法调用的上下文对象这时候通常称其为 this 值在网页的全局上下文中调用函数时this 指向 windows谁调用这个函数this就指向谁。 这个 this 到底引用哪个对象必须到函数被调用时才能确定 栗子 window.color red;
let o { color: blue
};
function sayColor() { console.log(this.color);
}
sayColor(); // red
o.sayColor sayColor;
o.sayColor(); // blue 在箭头函数中this引用的是定义箭头函数的上下文。箭头函数在哪里定义的this就指向谁栗子 this 引用的都是 window 对象因为这个箭头函数是在 window 上下文中定义的。 window.color red;
let o { color: blue
};
let sayColor () console.log(this.color);
sayColor(); // red
o.sayColor sayColor;
o.sayColor(); // red caller ECMAScript 5 也会给函数对象上添加一个属性caller。这个属性引用的是调用当前函数的函数 栗子 function outer() { inner();
}
function inner() { console.log(inner.caller);
}
outer();
//前面有说过 arguments.callee 是指向arguments所在的函数所以可以改为
function outer() { inner();
}
function inner() { console.log(arguments.calle.caller);
}
outer(); 打印结果 函数属性与方法 属性 前面提到过ECMAScript 中的函数是对象因此有属性和方法。每个函数都有两个属性length和 prototype。 length 属性保存函数定义的命名参数的个数 栗子 function sayName(name) { console.log(name);
}
function sum(num1, num2) { return num1 num2;
}
function sayHi() { console.log(hi);
}
console.log(sayName.length); // 1
console.log(sum.length); // 2
console.log(sayHi.length); // 0 方法 函数还有两个方法apply()和 call()。 这两个方法都会以指定的 this 值来调用函数即会设置调用函数时函数体内 this 对象的值。 apply()和 call()真正强大的地方并不是给函数传参而是控制函数调用上下文即函数体内 this 值的能力。 apply()方法接收两个参数函数内 this 的值和一个参数数组 栗子 window.color red;
let o { color: blue
};
function sayColor(a,b,c) { console.log(this.color,a,b,c);
}
sayColor(1,2,3); // red,1,2,3
sayColor.apply(this,[2,3,4]); // red,2,3,4
sayColor.apply(window,[2,3,4]); // red ,2,3,4
sayColor.apply(o,[2,3,4]); // blue,2,3,4 call()方法第一个参数函数内 this 的值而剩下的要传给被调用函数的参数则是逐个传递的。 栗子 window.color red;
let o { color: blue
};
function sayColor(a,b,c) { console.log(this.color,a,b,c);
}
sayColor(1,2,3); // red,1,2,3
sayColor.call(this,2,3,4); // red,2,3,4
sayColor.call(window,2,3,4); // red ,2,3,4
//而在使用 sayColor.call(o)把函数的执行上下文即 this 切换为对象 o 之后结果就变成了示blue了。
sayColor.call(o,2,3,4)// bule,2,3,4 总结 1. 区别 call传递的参数是序列123apply传递的参数是集合型[123]2. 相同点 call和apply是替换前面函数内部的this指针以及传递参数。功能可以自动执行前面的函数都有两个参数a. 替换的对象 b. 传递的值 bind() ECMAScript 5 出于同样的目的定义了一个新方法bind()。bind()方法会创建一个新的函数实例 其 this 值会被绑定到传给 bind()的对象。 栗子 window.color red;
var o { color: blue
};
function sayColor() { console.log(this.color);
}
let objectSayColor sayColor.bind(o);
objectSayColor(); // blue