2016-09-02-day11 am
1.*****Function
1.匿名函数:
- 什么是: 在创建时,不被任何变量引用的函数。
- 为什么: 节约内存
- 何时: 只要一个函数只用一次,就释放
- 如何使用:
1).回调(callback): 创建一个函数后,将函数对象传递给其他函数调用。
比如:
arr.sort( //自定义比较器函数
function(a,b){return a-b}
);
arr.replace(reg/*正则*/,function(){
return xxx;
})
2).自调: 创建一个函数,然后立刻调用执行,执行后,立刻释放
(function(参数列表){
函数体;
return 返回值;
})(参数值);
- 何时: 如果一项任务仅执行一次,且使用了仅属于当前任务的变量时,就要将变量和任务代码封装在一个匿名函数中,自调
比如以下代码只执行一次,原来的写法如下
var now=new Date()
f1 function(now){
console.log('开始加载内容'+now.toGMTString());
}
f1();
采用自调的方式,更改为如下,节约内存,又封装了局部变量
(function(date){
console.log('开始加载内容'+date.toGMTString());
})(new Date())
2.****作用域和作用域链:
- 作用域(scope): 一个变量的可用范围。( 本质: 存储变量的对象)
- 函数的原理:
1.程序开始执行:
1)创建ECS(Execution Context Stack,执行环境栈):顺序保存正在调用的函数的执行环境
2)向ECS中压入第一个EC(EC:函数调用时,引用所有变量的元素)
3)创建全局作用域对象window:
4)EC引用window
以下是一个简单的函数例子,下面分析一下执行这段代码时,程序开始执行时都做了些什么
var a=3;
function fun(){
var a=100;
a++;
console.log(a);
}
fun();//101
console.log(a);//3
程序先创建了一个ECS,用来顺序保存执行环境,可以理解为栈或数组,js在底层调用主程序,压入main(),这个主程序就是EC,同时创建了全局作用域对象window,然后EC引用window,引擎小人现在在EC上。
然后程序开始执行,var a=3,
2.函数定义时: 创建函数对象
在全局创建函数名变量引用函数对象
在函数对象中添加一个scope属性:
引用函数来自的作用域对象
3.函数调用时:
向ECS中压入要调用函数的执行环境EC
创建函数作用域对象(活动对象AO):
AO:保存本次函数调用时,使用的所有局部变量的对象。
在AO中添加parent属性,引用函数对象的scope属性指向的作用域。
EC中的scope chain属性引用AO对象
4.函数调用后: 本次调用的函数的EC出栈
导致:AO释放
导致: 局部变量一同释放
- 作用域链(scope chain):
由各级作用域对象,逐级引用形成的链式结构
控制变量的使用顺序:
优先使用AO中的局部变量
如果局部没有,才延作用域链向下找,到window
如果window也没有才报错
3.*****闭包(closure):
重用局部变量,并保护变量不受污染的机制
为什么:
全局变量: 随处可用,可反复使用
缺: 极易被污染
局部变量: 不会被污染
缺:仅函数内可用,且不可重用
何时: 只要希望重用一个局部变量,又不希望局部变量被污染时
如何: 3步:
Step1: 将受保护的变量和操作变量的函数封装在一个外层函数中定义。
Step2: 外层函数,要将内层函数队形返回
Step3: 使用者调用外层函数,获得内层函数对象。
pm
正课:
-
*****Function
闭包 -
*****OOP
-
*****Function:
闭包:
如何: 3步: -
用外层函数封装受保护的变量和操作变量的内层函数
-
外层函数返回内层函数的对象
-
使用者调用外层函数,获得内层函数的对象。
三大特点:
- 外层函数
- 受保护的变量
- 内层函数
BS:
- 先找受保护的变量:
- 外层函数的局部变量
- 内层函数中被使用
判断当外层函数结束时,受保护的变量最终的值。 - 找外层函数返回的内层函数对象:
- return function
- 直接给全局变量赋值一个function
- 将多个内层函数放入数组或对象中,批量返回。
结论:
同一次外层函数调用返回的多个内层函数对象共用同一个受保护的变量。
先后两次外层函数调用返回的两个内层函数对象,分别使用各自的受保护的变量副本,互不影响。
优: 重用变量,且保护其不被篡改
缺: 占用更多的内存空间。
无法自动释放
2.*****面向对象:
什么是: 程序中都是用对象来描述现实中一个具体事物。
什么是对象: 程序中封装现实中一个具体事物的属性和功能的程序结果
事物的属性,会成为对象的属性
事物的功能,会成为对象的方法
为什么: 更符合人的想法。
如何使用: 2步:
1. 先用对象描述一个事物的属性和功能
-创建对象/封装
封装: 将事物的属性和功能集中定义在一个对象中。
3种:
1.对象直接量:
var obj={
属性名:值,
方法名:function(){
//对象的方法中,要使用对象自己的属性,必须写成"this.属性名"
//当前对象的...
}
}
this: 指正在调用方法的.前的对象
***js中一切对象底层都是hash数组
2.用new:
var obj=new Object();
obj.属性名=值;
obj.方法名=function(){
...this.属性名...
}
其中new可省,()也可省,但不能同时省略。
3.反复创建多个相同结构的对象:
2步:
1.定义构造函数:
什么是: 专门描述一类对象统一结构的函数。
何时: 只要反复创建多个相同结构的对象时。
为什么: 代码重用——优
如何:
function 类型名(属性参数){
this.属性名=属性参数;
this.方法名=function(){
...
}
}
2.用new调用构造函数:
var obj=new 类型名(属性值);
new: 4件事儿:
1. 创建了一个空对象:
2. ?
3. 用空对象调用构造函数
4. 返回新对象地址给变量
缺: 没有解决内存浪费的问题
2. 再按照逻辑的需要,依次调用对象中的功能来操作对象的属性。
访问对象的成员(属性和方法):
操作对象的属性: obj.属性名
其实就是一个放在对象中的普通变量而已。
特殊:
访问对象中没有的属性,不报错,返回undefined.
为对象中不存在的属性赋值,不报错,会自动添加属性,保存属性值。
调用对象的方法: obj.方法名();
其实就是一个放在对象中的普通函数而已。
网友评论