1. 静态成员和实例成员
静态成员表示的是静态方法和静态属性的概念,所谓的静态,就是由构造函数所提供的。
实例成员表示的是实例方法和实例属性,所谓的实例就是由构造函数所创建的对象。
一般工具型方法都是由静态成员提供,一般与实例对象有关的方法由实例成员表示。
2. 函数的构造函数Function
Function的存在目的是动态创建函数。
在js中使用Function可以实例化函数对象,也就是说在js中,函数与普通对象一样,也是一个对象类型,可以使用对象的动态特性,可以利用构造函数创建函数,可以创建其他对象,函数是js中的一等公民,是唯一可以限定变量作用域的结果。
new Function( agr0,arg1,arg2,......,argN,body);Function中的参数全部是字符串,该构造函数的作用是将参数链接起来组成函数,如果参数只有一个,那么表示函数体;如果参数有多个,那么最后一个参数表示函数体,前面的所有参数表示函数的参数;如果没有参数,表示创建一个空函数。
<script type="text/javascript">
function foo(){ console.log('Hello'); } // 传统写法
var func = new Function( 'console.log("Hello");' ); // 与上面等价,注意参数为字符串
function foo(){}
var func = new Function();
function foo(num) {console.log(num);}
var func = new Function('num',"console.log(num);"); // 注意参数的表示
// 任意的一个函数,都是相当于Function的实例,类似于{}与new Object()的关系
function foo(){} // 告诉解释器,有一个对象叫foo,是一个函数,相当于new Function()得到一个函数对象
// 函数应有_proto_属性,其构造函数是Function,函数应继承自Function.prototype,Function.prototype继承自Object.prototype
</script>
函数都是Function的实例,故Object函数是Function的一个实例,Object作为对象是继承自Function.prototype的,Function是自己的构造函数。
3. 函数原型链结构
4. Function原型链结构
在js中,任何对象的老祖宗都是Object.prototype,任何函数的老祖宗都是Function.prototype。
5. eval() 函数
计算 JavaScript 字符串,并把它作为脚本代码来执行,如果参数是一个表达式,eval() 函数将执行表达式;如果参数是Javascript语句,eval()将执行 Javascript 语句。
<script>
eval("x=10;y=20;document.write(x*y)"); // 200
document.write("<br>" + eval("2+2")); // 4
document.write("<br>" + eval(x+17)); // 27
// 将{}解释成代码块,name:数据,将:解释称标记语言
console.log(eval( "{name: 'Karry'}" ) ); // Karry
console.log(eval("({name: 'Karry', age: 19})")); // 返回对象,()将数据转换成表达式
</script>
6. 词法作用域&作用域链
(1)词法作用域概念:代码在编写过程中体现出来的作用范围,代码一旦写好,不用执行,作用范围就已经确定好了。
(2)作用规则:函数允许访问函数外的数据;整个代码结构中只有函数可以限定作用域,块{}不限定作用域;作用规则首先使用提升规则分析;如果当前作用域中有名字了,就不考虑外面的名字。
(3)作用域链概念:代码至少有一个作用域即全局作用域,如果代码中有函数,则又构成一个作用域,将所有作用域列出来,可以有一个结构,函数内指向函数外的链式结构。
(4)作用域链图:图中一个方块代表一个声明。
<script>
var num = 123;
function f1() {
console.log(num);
}
function f2() {
var num = 456;
f1(); // 此处是调用
}
f2(); // 123
</script>
7. 闭包
(1)概念:一个具有封闭的、对外不公开的包裹结构或空间,在js中函数可以构成闭包,不允许外界直接访问,一般用于保护私有数据。
(2)访问闭包里面数据的示例
<script type="text/javascript">
function foo() {
var num = Math.random();
function func(){return num;}
return func;
}
var f = foo(); // f直接访问num
var res1 = f(); // 0级链无法访问1级链的数据,所以间接的0级链操作2级链的函数,来访问1级链的数据
var res2 = f(); // 与res1相等
</script>
(3)函数科里化(高阶函数):定义一个函数,该函数返回一个函数。
<script>
function foo( arg1 ) {
function func( arg2 ) {}
return func;
}
foo( arg1 )( arg2 );
</script>
(4)闭包的应用
<script>
function foo() {
var num1 = Math.random();
var num2 = Math.random();
return { // 获得超过一个数据,封装成对象
num1: function(){ return num1; },
num2: function(){ return num2; }
};
}
</script>
<script>
function foo() {
var num = Math.random();
return {
get_num: function() { return num; }, // 获取函数中的数值
set_num: function( value ) { num = value; } // 设置函数中的数值
}
}
var o = foo();
var num = o.get_num();
o.set_num(0.4);
</script>
(5)闭包的性能问题:函数执行需要内存,那么函数中定义的变量,会在函数执行结束后自动回收,凡是因为闭包结构被引出的数据,如果还有变量引用这些数据的话,那么这些数据就不会被回收,因此在使用闭包的时候,如果不使用某些数据了,一定要赋值null。