您的位置:首页 > Web前端 > JavaScript

JS高级(作业域链,闭包,面向对象)

2016-05-29 20:51 423 查看


JS高级(作业域链,闭包,面向对象)


作用域链


定义

变量在当前环境now、内部环境f1、内部深层环境f2/f3....都起作用的现象形成了一个链条,这个链条就称为变量的"作用域链"
<script type="text/javascript">
var title="链条“;
console.log("now"+title);
function f1(){
console.log("f1"+title);
function f2(){
console.log("f2"+title);
function f3(){
console.log("f3"+title);
}
f3();
}
f2();
}
f1();
</script>


作用域链的作用

变量必须“先声明、后使用”

函数可以“先使用、后声明”,原因是函数有“预加载”过程(函数声明先于其他执行代码进入内存)。本质还是函数的声明在前,使用在后。

<script type="text/javascript">
f1();
function f1(){
console.log("f1"+title);
}
</script>

内部环境可以访问外部环境的变量,反之不然
变量的作用域是声明时决定的,而不是运行时


闭包


什么是闭包

闭包就是一个函数,两个函数彼此嵌套,内部函数就是闭包 形成闭包条件是内部函数需要通过return给返回出来.
<script type="text/javascript">
function f1(){
var name="tom";
var age=18;
function f2(){
console.log("名字:"+name+",年龄:"+age);
}
return f2;
}
var ff=f1();//这就是一个闭包,ff与f2共同指向一个function
ff();//名字:tom,年龄:age
</script>

解释

f1()调用完成后,垃圾回收器会回收name和age,但是因为ff又去指向function,这样function内部的age和name仍然存在,并且与外部变量无关


闭包使用规则

同一个闭包机制可以创建多个闭包函数出来,它们彼此没有联系,都是独立的。 并且每个闭包可以保存自己个性化的信息。
<script type="text/javascript">
function f1(){
var name="tom";
var age=18;
function f2(){
console.log("名字:"+name+",年龄:"+age);
}
return f2;
}
var ff1=f1();
var ff2=f2()
var ff3=f3();
</script>


闭包案例

闭包生成数组元素
<script type="text/javascript">
var arr=new Array();
for(var i=0;i<4;i++){
arr[i]=function () {
console.log(i);
return i;
}
}
arr[2]();  //4
arr[1]();  //4
arr[0]();  //4
arr[3]();  //4
</script>

使用闭包
<script type="text/javascript">
var arr=new Array();
for(var i=0;i<4;i++){
arr[i]=f1(i);
}
function f1(n) {
function f2() {
console.log(n)
}
return f2;
}
arr[0]();  //0
arr[1]();  //1
arr[2]();  //2
arr[3]();  //3
</script>

闭包事件操作
<script type="text/javascript">
window.onload=function () {
var cars=document.getElementsByTagName('li');
//可以利用闭包给每个元素设置独立的函数处理
//并且函数内部也有独特的下标信息供访问
for(var i=0;i<3;i++){
cars[i].onmouseover=over(i);
cars[i].onmouseout=out(i);
}
var col=['red','green','blue'];
function over(n) {
function f2() {
cars
.style.backgroundColor=col
;
}
return f2;
}
function out(n) {
function f2() {
cars
.style.backgroundColor="";
}
return f2;
}
}
</script>


面向对象操作

① 字面量方式创建
<script type="text/javascript">
var dog={name:'旺财',age:5,hobby:function () {
console.log("看家护院")
}};
//对已有成员丰富其对象
dog.color="yellow";
dog['weight']=80;
dog.run=function () {
console.log("在跑步");
}
//访问成员
console.log(dog.name);
dog.hobby();
dog['run']();
</script>


② 构造函数创建对象
<script type="text/javascript">
function Animal() {
//设置默认成员(通过this引用)
this.name="tom";
this.age=6;
this.run=function () {
console.log("在跑步");
}
}
var cat=new Animal();
console.log(cat);
cat.run();
</script>


③ Object方式创建对象
<script type="text/javascript">
var cat=new Object();
cat.eat="fish";
console.log(cat);
</script>


构造函数与普通函数区别

没有区别,就看使用,new就是构造函数,函数()就是普通函数调用。


函数的各种执行方式

① 普通函数调用

② 构造函数执行new

③ 作为对象的成员方法执行

④ 通过call和apply执行

call和apply可以明显控制变量污染的风险。

call无需声明新的成员出来,就可以直接使用其他函数或方法

<script type="text/javascript">
var cat={name:"tom",climb:function () {
console.log(this.name+"在爬树")
}};
var dog={name:"旺财",age:6};
var wolf={name:"灰太狼"};
cat.climb.call(cat);
cat.climb.call(dog);

</script>


apply()方法与call()方法类似,只是将函数test的所有的参数放在一个数组中而已。即:apply()方法只有两个参数,一个是obj对象,另一个是数组,这个数组中存放的是test函数的所有实参。

总结:是为了动态的改变this的指向


this都是谁

① 在函数/方法里边 代表调用该函数/方法的当前对象

② 在事件中,代表元素节点对象
divnode.onclick = function(){
alert(this.value);
}


③ 代表window

④ 可以任意代表其他对象

在call和apply使用的时候,可以任意设置被执行函数内部this的代表


获取构造器

构造器:使用什么元素实例化的对象,元素就称为该对象的构造器

对象.constructor; //获得构造器
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息