函数
1、定义
1.1函数声明
function test(){
}
function test(){
document.write('a');
document.write('b');
document.write('c');}
1.2函数表达式
1.2.1.命名函数表达式
var test = function abc(){
document.write('a');
}
1.2.2.匿名函数表达式------函数表达式
test();
var demo = function(){
document.write();
}
1.3函数通常为:高内聚,弱偶合
2、组成形式
2.1函数名称
如果有多个单词,第一个单词首字母小写,其他首字母大写,即小驼峰式
2.2参数
2.2.1形式参数,a,b
function sum(a, b){//默认定义a,b
if(a > 10){document.write(a - b);
}else if(a < 10){
document.write(a + b);
}else{
document.write(10)
}
}
2.2.2实际参数
sum(11, 2)
// 求形参长度
function sum(a){
for(var i = 0; i < arguments.length; i++){
console.log(arguments[i])
}
}
2.2.3求实参长度
function sum(a, b, c, d){
if(sum.length > arguments.length){
console.log('形参多了');
}else if(sum.length < arguments.length){
console.log('实参多了');
}else{
console.log('相等')
}
}
sum(11, 2, 3)
2.2.4不定参求和
function sum(){
//arguments[0,1,2,3,4,5,6]
var result = 0;
for(var i = 0;i < arguments.length;i++){
result += arguments[i];
}
console.log(result);
}
sum(1,2,3,4,5,6,7,8,9,10);
2.3返回值
return两点功能(同时生效)
2.3.1.终止
function sum(a, b){
console.log('a');
return;
console.log('b');
}
2.3.2.返回值
function myNumber(target){
return +target;
}
var num = myNumber('123');
console.log(typeof(num) + " " + num);
3、预编译
3.1函数里面定义的变量为局域变量
3.2 js运行三部曲
语法分析
执行之前先进性语法分析。
预编译
解释执行
3.3预编译
3.3.1
1、imply golbal暗示全局变量 :
即任何变量,如果变量未经声明就赋值,
此变量就为全局对象所有。
eg:a = 123;
eg:var a = b = 123;
2、一切声明的全局变量,全是window属性。
eg:var a = 123;===> window.a = 123;
function test(){
var a = b =123;
}
a为局部变量,b为全局变量
函数声明整体提升
变量 声明提升
3.3.2预编译四部曲
1、创建AO(Activation Object)对象(局部变量)
2、找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
3、将实参值和形参统一
4、在函数体里面找函数声明,值赋予函数体
生成一个GO(Global Object)对象(全局变量)
GO{ }
例子:
console.log(test);
function test(test) {
console.log(test);
var test = 234;
console.log(test);
function test( ){
}
}
test(1);
var test = 123;
4、作用域
4.1作用域精解
1[[scope]]:每一个JavaScript函数都有一个对象,对象中有些属性是我们可以访问,
但有些是不可以,这些属性仅供JavaScript引擎存取,[[scope]]就是其中的一个。
2[[scope]]指的就是我们所说的作用域,其中存储了运行期上下文的集合。
3作用域链:[[scope]]中所存储的执行期上下文对象的集合,这个集合成链式链接,
我们把这种链式连接叫做作用域链
4执行期上下文:(就是AO,GO,就是即时的作用空间,用完就不用了,
就是把作用域链干掉了)当一个函数执行时,会创建一个称为执行期上下文的内部对象。
一个执行期上下文定义了一个函数执行时的环境,函数每次执行时对应的执行器上下文都是独一无二的,所以多次调用函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行期上下文被销毁。
5查找变量:(在哪个函数里面中查找就从那个函数里面)从作用域的顶端依次向下查找。
5、闭包
5.1闭包的产生
当内部函数被保存到外部时,将会生成闭包。
闭包会导致原有作用域链不释放,造成内部泄露。(就是内存占用过多,内存余量不足)
5.2闭包的作用
5.2.1实现公有变量
eg:函数累加器.
function add(){
var count = 0;
function demo(){
count ++;
console.log(count);
}
return demo;
}
counter();
5.2.2可以做缓存(存储结构)
eg:eater
function eater(){
var food =""
var obj ={
eat : function (){
console.log("i am eating " + food);
food = myFood;
}
}
return obj;
}
var eater1 =eater();
eater1.push('banana');
eater1.eat();
5.2.3可以实现封装,属性私有化
eg:Person()
模块化开发,防止污染全局变量
6、立即执行函数
6.1定义:
此类函数没有声明,在一次执行过后即释放。适合做初始化工作。
针对初始化功能的函数
var num = (function (a, b, c){
var d = a + b + c * 2 - 2;
return d;
}(1, 2, 3));
6.2立即执行函数
针对初始化功能的函数
var num = (function (a, b, c){
var d = a + b + c * 2 - 2;
return d;
}(1, 2, 3));
(function (){}());w3c建议第一种
例如:
(function test(){
console.log('a');
}());
(function (){})();
只有表达式才能被执行符号执行
函数声明
function test () {
var a = 123;
}
test();
函数表达式
能被执行符号执行的表达式,函数名自动忽略
var test = function () {
console.log('a');
}()
下面这种不报错也不执行
function test(a, b, c, d) {
console.log(a + b + c + d);
}(1, 2, 3, 4);
6.3闭包实现吃东西
function test() {
var food = "apple";
var obj = {
eatFood : function (){
if(food != "") {
console.log("I am eating " + food +"!");
food = "";
}else{
console.log("There is nothing! empty!");
}
},
pushFood : function(myFood) {
food = myFood;
}
}
return obj;
}
var person = test();
person.eatFood();
person.eatFood();
person.pushFood('banana');
person.eatFood();
6.4一般用立即执行函数来解决闭包问题
function test() {
var arr = [];
for(var i = 0; i < 10; i ++){
(function (j) {
arr[j] = function () {
console.log(j);
}
}(i))
}
return arr;
}
var myArr = test();
for(var j = 0; j < 10; j++) {
myArr[j]();
}
function a() {
function b() {
var bbb = 234;
document.write(aaa);
}
var aaa = 123;
return b;
}
6.5常见的闭包问题:
function test(){
var liCollection = document.getElementsByTagName(‘li’);
for(var i = 0; i< liCollection.length; i++){
liCollection[j].onclick = function (){
console.log(j);
}
}
}
test();
解决方法:
function test(){
var liCollection = document.getElementsByTagName(‘li’);
for(var i = 0; i< liCollection.length; i++){
(function(j){
liCollection[j].onclick = function (){
console.log(j);
}
}(i))
}
}
test();
7、例题
7.1写一个函数
功能是告知你所选定的小动物的叫声
function scream(animal){
switch(animal){
case "dog" :
document.write('wang');
return;
case "cat" :
document.write('miao');
return;
case "fish" :
document.write('o~o~o~');
return;
}
}
7.2定义一组函数
输入数字,逆转并输出汉字形式。
function reverse(){
var num = window.prompt('input');
var str = "";
for(var i = num.length - 1; i >= 0; i --){
str += transfer(num[i]);
}
document.write(str);
}
function transfer(target) {
switch(target) {
case "1" :
return "壹";
case "2" :
return "贰";
case "3" :
return "叁";
}
}
7.3阶乘
function jc(n) {
if(n == 1) {
return 1;
}
return n * jc(n - 1);
}
7.4递归
function mul(n) {
//n的阶乘
if(n == 1 || n == 0){
return 1;
}
return n * mul(n - 1);
}
7.5斐波那契数列
fb(n) == fb(n - 1) + (n - 2);
function fb(n) {
if(n == 1 || n == 2) {
return 1;
}s
return fb(n - 1) + fb(n - 2);
}
7.6写一个方法,求字符串的字节长度
7.6.1
function retByteslen(target) {
var count = 0;
for(var i = 0; i < target.length; i++) {
if(target.charCodeAt(i) <= 255){
count ++;
}else if(target[i].charCodeAt(i) > 255){
count +=2;
}
}
console.log(count);
}
7.6.2优化
function retByteslen(target) {
var count = target.length;
for(var i = 0; i < target.length; i++) {
if(target.charCodeAt(i) > 255){
count ++;
}
}
console.log(count);
}
7.6.3再优化
function retByteslen(target) {
var count,
len;
count = len = target.length
for(var i = 0; i < len; i++) {
if(target.charCodeAt(i) > 255){
count ++;
}
}
console.log(count);
}
7.7“,”操作符
","操作符:返回,后面的内容
eg:
var f=(
function f() {
return “1”;
},
function g() {
return 2;
}
)();
console.log(typeof f);