《JavaScript权威指南》中是这样解释的:JavaScript变量在声明之前已经可用,JavaScript的这个特性被非正式的称为声明提前(hoisting),即JavaScript函数中声明的所有变量(但不涉及赋值)都被“提前”至函数的顶部。
从一个例子来看:
var scope = "global"; function myFunc(){ console.log(scope); var scope = "local"; }
控制台打印出来的不是“global”而是“undefined”,这是因为在myFunc这个函数的作用域中,局部变量scope声明被提前至函数顶部,而此时,scope仅声明,未赋值,因此输出undefined。实际上,上面的代码和下面的效果是一样的:
var scope = "global"; function myFunc(){ var scope; console.log(scope); scope = "local"; }
5 如何理解和应用JavaScript闭包
关于闭包具体的定义文献中给的概念很抽象,我认为闭包是一种使函数能够都去其它函数的局部变量的语法机制。
举个例子:
function outFunc(){ var name = "Vicfeel"; function inFunc(){ console.log(name); } return inFunc; } inFunc(); //控制台显示"Vicfeel"
这这个例子我们可以看出,在函数inFunc中依然可以访问outFunc的局部变量name。
闭包应用举例,模拟类的私有属性,利用闭包的性质,局部变量只有在sayAge方法中才可以访问,而name在外部也访问,从而实现了类的私有属性。
function User(){ this.name = "Vicfeel"; //共有属性 var age = 23; //私有属性 this.sayAge:function(){ console.log("my age is " + age); } } var user = new User(); console.log(user.name); //"Vicfeel" console.log(user.age); //"undefined" user.sayAge(); //"my age is 23"
要了解详细的闭包,推荐一下 阮一峰的网络日志-学习Javascript闭包(Closure)。
6 new构建对象的本质
function User(){ this.name = "Vicfeel"; this.age = 23; } var user = new User();
通过new操作符,实际上在构造函数User中完成了如下操作:
•创建一个新的对象,这个对象的类型是object;
•设置这个新的对象的内部、可访问性和prototype属性为构造函数(指prototype.construtor所指向的构造函数)中设置的;
•执行构造函数;
•返回新创建的对象。
function User(){ //this = {}; //this.constructor = User; this.name = "Vicfeel"; this.age = 23; //return this; } var user = new User();
如果构造函数默认返回的新创建的this对象,如果手动return 一个变量的话,如果该变量是原始类型则无效,如果是对象,则返回该对象。
7 JavaScript代理
当我们需要对很多元素添加事件的时候,可以通过将事件添加到它们的父节点而将事件委托给父节点来触发处理函数。
比如我们需要向一个ul中动态添加很多个li,需要遍历li逐个添加点击事件
<ul></ul> var count = 100; var ulList = document.getElementById("list"); //动态构建节点 for(var i = count;i--;){ var liDom = document.createElement('li'); ulList.appendChild(liDom); } //绑定点击事件 var liNode = ulList.getElementByTagName("li"); for(var i=0, l = liNodes.length; i < l; i++){ liNode[i].onClick = function(){ //li点击事件 } }
众所周知,DOM操作是十分消耗性能的。所以重复的事件绑定简直是性能杀手。而事件代理的核心思想,就是通过尽量少的绑定,去监听尽量多的事件。如何做呢?答案是利用事件冒泡机制,对其父节点ul进行事件绑定(Event Bubble),然后通过event.target来判断是哪个节点触发的事件,从而减少很多EventHandler的绑定。
var count = 100; var ulList = document.getElementById("list"); //动态构建节点 for(var i = count;i--;){ var liDom = document.createElement('li'); ulList.appendChild(liDom); } //绑定点击事件 var liNode = ulList.getElementByTagName("li"); liNode.onClick = function(e){ if(e.target && e.target.nodeName.toUpperCase == "LI") { // li点击事件 } }
发现新内容会持续更新...
您可能感兴趣的文章: