js this指针绑定问题 及闭包小析

来源:互联网 发布:大数据量表设计 编辑:程序博客网 时间:2024/06/05 11:32

tips : 本博客示例部分引用至
http://developer.51cto.com/art/200907/136245.htm
http://coolshell.cn/articles/6731.html

js this 指针绑定

对于学过c++的同学,对象方法定义时,并不会显示定义this作为参数,但是在调用时,编译器会默认将this 传入本方法,而此时this指向的是当前实例【对象】

#include <iostream>using namespace std;class Person{       public  string name;    private int age;    public Person(string name,int age) {        this.name = name;        this.age = age;    }    public void setAge(int age) {          this.age= age;    }    public void sayHellow(){           cout<< this.name << "say hellow to you" << endl;    } };

python 类的定义,显示指定this参数,但调用类方法时,有编译器默认绑定this 指向当前实例

class people:      name = ''    __age = Null    def __init__(self,name,age):          self.name = name         self.__age = age;    def speak(self):          print("%s is %d years" %(self.name,self.__age))  

对于JS这种脚本语言也不例外,函数或者对象方法 被定义时,并不存在this变量,只有函数或对象方法被调用时,this作为参数隐性的传入,这样以来,当前谁调用该函数或对象方法 this指针就指向谁

var name = "Kevin Yang";  function sayHi(){      alert("你好,我的名字叫" + this.name);  }  sayHi(); 

此时,sayHi()方法被执行,在js中所有变量,对象,函数都默认归属于window对象,
换句话说,执行sayHi()函数,其实是在执行window对象下sayHi()对象方法 标准写法 window.sayHi() ,只不过window一般可以省略
也就是说 执行sayHi()时,默认将当前对象window传入【将this绑定到window对象】

var name = "Kevin Yang";  function sayHi(){     alert("你好,我的名字叫" + this.name);  }  var person = {};  person.sayHello = sayHi;  person.sayHello()

此时sayHi()函数引用, 被赋值给person对象的sayHellow属性,当执行sayHello时,当前对象是person,所以this执行person,但是person对象中没有name属性,所以undefined

function sayHi(){     alert("当前点击的元素是" + this.tagName);  }      
<input name="btnTest" type="button" value="点击我" onclick="sayHi()">

当按钮被点击时,实际上执行的是下面代码

document.getElementById("btnTest").onclick = function(){      sayHi();  }  

此时的sayHi()实际上还是 执行widowl.sayHi()所以 sayHi()函数中 this指向的是window对象
可以改进如下:

function sayHi(el){     alert("当前点击的元素是" + el.tagName);  }  <input name="btnTest" type="button" value="点击我" onclick="sayHi(this)">

改进后执行过程如下:

document.getElementById("btnTest").onclick = function(){     sayHi(this);  }  

临时变量导致的this指针丢失

var Utility = {      decode : function(str){           return unescape(str);      },      getCookie : function(key){           var value = "i%27m%20a%20cookie";           return this.decode(value);      }  };  alert(Utility.getCookie("identity")) var getCookFunc = Utility.getCookie;alert(getCookFunc("identity")) 

当Utility对象下getCookie方法 赋值给全局变量 getCookFunc后,执行getCookFun()实际上是 window.getCookFun() ,当前对象是window,所以调用getCookFun时,window被默认传入【this指向window对象】


tips : 详细参加本博客参考文档材料,见博客尾部

闭包

闭包使得函数内容定义的局部变量可以被外部访问到
使得局部函数内部的局部变量在函数执行完成后可以继续存在
在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

function greeting(name) {    var text = 'Hello ' + name; // local variable    // 每次调用时,产生闭包,并返回内部函数对象给调用者    return function() { alert(text); }}var sayHello=greeting("Closure");sayHello()  // 通过闭包访问到了局部变量text

当在一个循环中赋值函数时,这些函数将绑定同样的闭包

function buildList(list) {    var result = [];    for (var i = 0; i < list.length; i++) {        var item = 'item' + list[i];        result.push( function() {alert(item + ' ' + list[i])} );    }    return result;}function testList() {    var fnlist = buildList([1,2,3]);    // using j only to help prevent confusion - could use i    for (var j = 0; j < fnlist.length; j++) {        fnlist[j]();    }}

buildList()函数执行完成后,buildList函数内容定义的局部变量item , i 并没有销毁,因为buildList函数内部定义了匿名函数,并将匿名函数引用压入result列表中,最后返回result列表,赋值给testList函数内部定义的局部变量 fnlist ,
匿名函数【闭包】依赖父函数对象【buildList】,所以只要匿名函数引用还存在,垃圾回收机制就不会销毁buildList函数对象,buildList函数内部定义的局部变量也就依然存在于内存中。
当buildList函数内for循环执行完成后,i=4, item=’item’ + list[3]; 所以当循环执行闭包时,读取的变量i都是4,变量item都是’item’ + list[3]


参考:
http://coolshell.cn/articles/6731.html
http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html
https://zh.wikipedia.org/wiki/TypeScript
http://bonsaiden.github.io/JavaScript-Garden/zh/#function.closures

0 0
原创粉丝点击