JavaScript之深入理解【函数】

一 参考文献
  《JavaScript忍者秘籍》
 
二 函数特征总结
  1. 函数是【第一型对象(first-class object)】:可以像这门语言的其它对象一样使用
    函数可以共处,可以将其视为其它任意类型的JavaScript对象
    普通的JavaScript数据类型,函数可以被任意变量进行引用,
    或者声明成对象字面量,甚至可将其作为函数参数进行传递。
    ①可以通过【字面量】[创建]
    ②可以[赋值]给【变量】、【数组】或【其他对象的属性】
    ③可以作为一个独立实体的【参数】[传递]给函数(见样例1)。
    ④可以作为【函数的返回值】进行[返回]
    ⑤可以拥有[动态创建并赋值]的【属性
    ⑥可以在【任何地方】[创建]函数(即 只要能使用本门语言表达式的地方,就能创建函数,包括:匿名函数、即时函数等
  2. 浏览器的事件轮询
    ①事件相互穿插发生。
      浏览器事件[页面加载完成、页面卸载]、
      网络事件
      用户事件[鼠标点击、移动、按键]、
      计时器事件
    ②浏览器的事件轮询是【单线程】的。
    ③每个事件都在自己的生命周期中进行处理,所有其他事件必须等到这个事件处理结束后才能继续处理。
 
  3. 回调概念
    定义:
       ①当我们定义一个(回调)函数稍后执行,无论何时定义、或者何处执行(在浏览器执行海曙其他地方执行)
      ②定义一个函数,以便其他一些代码在适当的时机再回头调用它(>回调函数)。
      ③可以将函数作为参数传递给另一个函数,并在随后对该函数进行调用
      样例1
function useless(callback){
	return callback();
}

var text = 'Johnny';
console.log(useless(function(){  return text; }) == text);//true 
      样例2
var count = 1;
var MAX_COUNT = 2;
function A(messageA,fn1,arg1){
	console.log("A:",messageA);
	C("A call C");
	fn1(arg1);
	setTimeout(B("A call B once again after 1000ms"), 1000);//A再次回调B,二者形成了双向沟(调)通(用)
}
function B(messageB,fn2){ //启动入口:B(" startup from B");
	console.log("B:",messageB);
	if(count < MAX_COUNT){
		count++;
		A("B call A",function(msg){
			console.log(msg);
			},"B call A's others arg/function");
	}
}
function C(messageC,fn3){
	console.log("C:",messageC);
	B("C call B");
}

 test/output:

B("Startup from B");
B: Startup from B
A: B call A
C: A call C
B: C call B
B call A's others arg/function
B: A call B once again after 1000ms

  4.函数声明

  格式:function [名称可选]([arg1,arg2,...,argN]) { ... }

    []表示:可选,非必须

  5.作用域和函数

    意义:当我们声明一个函数时,不仅要关注该函数可用作用域,还要关注该函数自身所创建的作用域,以及函数内部的声明是如何影响这些作用域的。

    特征:

      1.在JavaScript中,作用域是由function进行声明的,而不是代码块【()、{}等】

         比如:if(...) {  } //并不能像其他语言一样形成作用域

      2.变量声明的作用域开始于声明的地方结束于所在函数的结尾,与代码嵌套无关。

      3.机制提升:命令函数的作用域是指声明该函数的整个函数范围,与代码嵌套无关。

      4.对于作用域声明全局上下文就像一个包含页面所有代码的超大型函数

function outer(){
	assert(typeof outer == 'function',"1 outer() is in scope"); //true
	assert(typeof inner == 'function',"2 inner() is in scope"); //true
	assert(typeof a == 'number',"3 a is in scope");
	assert(typeof b == 'number',"4 b is in scope");
	assert(typeof c == 'number',"5 c is in scope");

	var a = 1;
	function inner(){
	assert(typeof inner == 'function',"6 inner() is in scope"); //true
	assert(typeof a == 'number',"7 a is in scope"); //true
	assert(typeof b == 'number',"8 b is in scope"); //true
	assert(typeof c == 'number',"9 c is in scope"); //true
}
	var b = 2;
	if(a == 1){
	assert(typeof a == 'number',"10 a is in scope"); //true
	assert(typeof b == 'number',"11 b is in scope"); //true
	assert(typeof c == 'number',"12 c is in scope");
		var c= 3;
	}
	assert(typeof a == 'number',"13 a is in scope"); //true
	assert(typeof b == 'number',"14 b is in scope"); //true
	assert(typeof c == 'number',"15 c is in scope"); //true
	inner();
}

outer();

assert(typeof outer == 'function',"16 outer() is in scope"); //true
assert(typeof inner == 'function',"17 inner() is in scope");
assert(typeof a == 'number',"18 a is in scope");
assert(typeof b == 'number',"19 b is in scope");
assert(typeof c == 'number',"20 c is in scope");

output:

1 outer() is in scope
2 inner() is in scope
3 a is in scope
4 b is in scope
5 c is in scope
10 a is in scope
11 b is in scope
12 c is in scope
13 a is in scope
14 b is in scope
15 c is in scope
6 inner() is in scope
7 a is in scope
8 b is in scope
9 c is in scope
16 outer() is in scope
17 inner() is in scope
18 a is in scope
19 b is in scope
20 c is in scope

s

原文地址:https://www.cnblogs.com/johnnyzen/p/10211301.html