part1 ---------------------------------------------------------------------------------------------------------

1. 前言

这两天看了一下TOM大叔的《深入理解js系列》中的基础部分,依据自己的实际情况,做了读书笔记,记录了部分easy绊脚的问题。写篇文章,供大家分享。

2. 关于HTMLCollection的“实时查询”

var divs = document.getElementsByTagName("div"),
i;
for (i = 0; i < divs.length; i++) {
//……
}

以上代码中,会出现性能问题。问题就在于divs是一个HTMLCollection类型的对象,这样的类型在每次获取数据时,都会再又一次从dom中分析计算。因此,这里的for循环中,每一步循环都会运行一次divs.length的计算,都会令浏览器再又一次遍历一遍dom树。

所以,应该在循环之外,早早的计算出divs的length属性值。例如以下:

var divs = document.getElementsByTagName("div"),
i,
length = divs.length;
for (i = 0; i < length; i++) {
//……
}

3.  for..in...时,注意hasOwnProperty验证

var obj = {
a: 10,
b: 20
}; // 注意词句代码
Object.prototype.c = 30; var item;
for (item in obj) {
console.log(item);
}

以上代码中,注意中间标凝视的句子。这句代码加与不加,会对以下的for..in..循环产生影响。加上了就输出“c”,不加就不输出“c”。道理非常easy,for..in..循环不光能遍历obj对象本身就有的属性,还能遍历obj原型中的属性。

要想屏蔽掉原型中的属性,就用hasOwnProperty函数,例如以下:

           for (item in obj) {
if (obj.hasOwnProperty(item)) {
//if (Object.prototype.hasOwnProperty.call(obj, item)) {
console.log(item);
}
}

这两句if推断语句,都能够用,效果是一样的。第一个代码可读性好,第二个效率相对较高。建议,没有特殊情况,用第一个就可以。

4. 老问题:循环中生成函数/事件的闭包问题

var events = [],
i = 0;
//循环创建函数
for (; i < 10; i++) {
events[i] = function () {
console.log(i);
};
} //验证结果
for (i = 0; i < events.length; i++) {
events[0]();
}

先看以上代码,有js开发经验的人肯定都非常熟悉,可是有的人知道,有的人不知道。按照以上代码,循环遍历events数组,运行数组元素中的函数,这10个函数都会打印出什么数字?答案是:全都会输出“10”。以下解释一下原因:

在每一个函数生成/被创建时,系统都会给它分配一个变量的环境,这个环境中也包含闭包的数据。可是,当多个环境,公用一个闭包的数据时,是一种引用的关系,这是重点。引用,不是复制。假设改变了这个公用数据,这些公用的环境获取时,也是改变后的数据。

所以,在创建第一个函数时,i === 0,第一个函数引用的闭包中i的值就是0;第二个函数被创建时,i === 1,这是,第一个、第二个两个函数应用闭包中i的值,都是1。以此类推,直到第十个函数创建时,i === 9;可是在for循环的最后一步,又运行了 i++;所以i === 10。

明确了吗?

想要改变这个问题,想要每一个函数都输出不同的数值,那就须要不让每一个函数都公用一个闭包——让每一个函数使用单独的闭包数据,不共享。仅仅需讲for循环创建函数的部分改动为:

//循环创建函数
for (; i < 10; i++) {
events[i] = (function (index) {
return function (index) {
console.log(index);
}
})(i);
}

此时,i作为參数,传入匿名自己主动运行函数,赋值给index參数。这个匿名函数的变量环境,就把index保存了下来,而不会随着i的变化而变化。这就是要点。

欢迎关注微博:weibo.com/madai01

part2-----------------------------------------------------------------------------------------------------------

1. 前言

昨天写了《js便签笔记(11)——浏览TOM大叔博客的学习笔记 part1》,简单记录了几个问题。part1的重点还是在于最后那个循环创建函数的问题,也就是多个子函数公用一个闭包数据的问题。假设认为有兴趣,能够再又一次翻出来看看。

今天继续把剩下的问题写完。

2. 作用域链

学js的人,即使0基础入门的也都知道“原型链”,可是“作用域链”,可能好多人没有听说过。大部分人都知道或者听说过“闭包”,可是可能有好多人不知道闭包事实上和作用域链有莫大的联系。假设理解闭包不从作用域链開始理解,那么你就仅仅能理解闭包的皮毛。

我也是从TOM大叔的这些博客中才了解到作用域链的,之前也看过了很多本书籍,都没有非常清晰的展开作用域链这个概念。事实上作用域链简单说来也好理解,例如以下代码:

        var x = 10;
function fn() {
var y = 20;
return function () {
var z = 30
console.log(x + y + z);
}
}

上面代码中,假设想要打印 x+y+z 的值,就必需要遍历三个层次的上下文环境或者作用域,这事实上和原型链的结构表现形式类似。但要细细将来,连同闭包图文并茂的说明确,需要非常多内容。

此处不再深入进去,以后有机会再另起一篇具体介绍。

3. 二维链查找

上文讲到通过作用域练向上查找变量,实际在查找变量的过程中,是使用“二维链查找”——“作用域链” + “原型链”。看例如以下代码:

       Object.prototype.x = 10;
function fn() {
var y = 20;
return function () {
var z = 30
console.log(x + y + z);
}
}

这份代码跟上文中演示作用域链的代码差点儿相同,可是它却通过 Object.prototype.x = 10; 这么一句话,表现出了原型链在当中的作用。

因此,在查找变量值时,是同一时候兼顾原型链和作用域链两个方向的,即“二维链查找”。

4. 独立作用域仅仅能通过函数来创建

这句话的下半句是——不能通过if/for等语句块来创建。后半句大家可能知道,可是它的本质确实前半句——独立作用域仅仅能通过函数来创建(除了独立作用域之外,剩下的就是全局作用域)。既然独立作用域仅仅能通过函数来创建,那么函数中不论什么地方的自由变量就都是函数层级的,因此,下面代码希望不要再次出现:

5. 隐式全局变量的本质

var a = 10;
b = 20;

以上两句代码,看似都是声明两个全局变量,可是依照TOM大叔说的,仅仅有var才干声明一个变量,也就是 var a = 10; 是真正的声明变量。

而下一句 b = 20,事实上是相当于设置window的一个属性值而已。

因此,第一句的本质是声明一个全局变量;第二句的本质是设置window的一个属性值。

当然,不推荐用第二句的形式。

6. 函数声明和函数表达式的不同

js定义函数的方法有多种,但看看下面这段代码:

fn();
var fn = function() { //函数表达式
alert(123); // 报错
}
//------
fn();
function fn() { //函数声明
alert(123); // 123
}

两种函数定义方式,却得出不一样的结果。

此处我当时没有具体看,由于这样使用的情况不是非常多,所以就没有过深入的细看,仅仅是做了个标记。假设有了解的朋友,不放解释一下。

7.js使用静态作用域

在part1中讲过,当一个函数作为參数被传入,后者作为一个值被返回的时候,连同它一块被传递的,是它的作用域。也就是咱们常说的闭包。且看例如以下代码:

var x = 10;
function foo() {
alert(x);
}
(function (funarg) {
var x = 20;
funarg(); // 10, 不是20
})(foo);

foo是一个函数,把它作为參数传入进还有一个函数中运行,连同一起传递的,是foo的作用域。而foo使用的是静态作用域,当中的变量x在传递的时候已经被静态赋值,不会受其它环境下x变量的影响。

这个道理也相同适用于函数作为返回值。例如以下:

function fn() {
var x = 10;
return function () {
alert(x);
}
}
var ret = fn();
var x = 20;
ret(); // 10,不是20

很多其它内容请关注我的微博

javascript - 浏览TOM大叔博客的学习笔记的更多相关文章

  1. js便签笔记(12)——浏览TOM大叔博客的学习笔记 part2

    1. 前言 昨天写了<js便签笔记(11)——浏览TOM大叔博客的学习笔记 part1>,简单记录了几个问题.part1的重点还是在于最后那个循环创建函数的问题,也就是多个子函数公用一个闭 ...

  2. js便签笔记(11)——浏览TOM大叔博客的学习笔记 part1

    1. 前言 这两天看了一下TOM大叔的<深入理解js系列>中的基础部分,根据自己的实际情况,做了读书笔记,记录了部分容易绊脚的问题.写篇文章,供大家分享. 2. 关于HTMLCollect ...

  3. hexo博客的学习笔记

    这篇文章主要的作用是作为 .md文件打开,内部的格式为一个初学者对hexo以及markdown语法运用的笔记 1.Hexo的写文格式 最开始为文章的属性部分,以三横杠-开始,-结束.里面记录了文章的标 ...

  4. 我的第一篇博客----LCS学习笔记

    LCS引论 在这篇博文中,博主要给大家讲一个算法----最长公共子序列(LCS)算法.我最初接触这个算法是在高中学信息学竞赛的时候.那时候花了好长时间理解这个算法.老师经常说,这种算法是母算法,即从这 ...

  5. Git--廖雪峰的博客的学习笔记

    为了督促自己能看完这个网站的学习教程,边看边做了些简要的笔记,记录了常用命令,其实也就是自己打了些简单的命令,好多直接就粘贴过来了,也算是一个学习的证明吧,想按详细的教程,还是要去博主的园子学习啊地址 ...

  6. 关于Kean博客的学习

    由于我从事设计行业,使用Autocad进行绘图是一件单调但是拥有乐趣的工作. 大约在一年前,接触到了CAD的二次开发的内容,它使我感到新奇,并且决定花时间来研究相关的知识.这时我在网上浏览到了Kean ...

  7. 在技术胖博客上学习ES6遇到的坑和想法

    第一节:ES6的开发环境搭建 坑1:全局安装babel-cli已经不被官方推荐,改为局部安装(cnpm install babel-cli --save-dev): 坑2:babel src/inde ...

  8. Django开发个人博客入门学习经验贴

    [写在前面] 入门学习搭建个人博客系统首先还是参考大佬们的经验,记得刚入手Django的时候,一篇博客大佬说过一句话,做技术的不要一开始就扎头于细节中,先把握整体框架,了解这个对象之后再去了解细节,进 ...

  9. GitHubPage博客搭建学习专栏

    Hexo NexT 博客本地搭建指南 Hexo NexT 博客与Github page 关联指南 Hexo NexT 博客后台管理指南

随机推荐

  1. tomcat path设置

    zjtest7-app:/usr/local/apache-tomcat-7.0.55_8082/logs# netstat -nap | grep 8082 tcp 0 0 :::8082 :::* ...

  2. GitHub上项目配置和导入eclispe的问题解决

    在github上下载的工程文件导入的时候总是遇到各种各样的问题,昨天晚上瞎忙一晚上查资料没搞定.早上找高手请教了一下,一起弄了好一会终于解决了,这里记录一下方法解决的具体方法步骤. 本方法适用于离线导 ...

  3. [Java 8] (6) Lambda与资源管理

    资源处理 Java本身自带了垃圾回收(Garbage Collection)功能.可是仅仅有垃圾回收的目标是内部资源(Internal Resource),典型的比方堆上分配的内存区域等.对于外部资源 ...

  4. 开源中国IOSclient

    我想看看别人开发项目.通过吸收经验,然后找到开放的中国,丹尼尔一些网上也开发了自己的开源在中国client 在网上看到很多网友说,不能下载东西像安装,我带来了我的方式,其中的一些朋友想帮忙. http ...

  5. java输出换行的标准姿势"line.separator"

    java中写.txt文件,实现换行的几种方法: 1.使用java中的转义符"\r\n": windows下的文本文件换行符:\r\n linux/unix下的文本文件换行符:\r ...

  6. python爬虫抓站的一些技巧总结

    使用python爬虫抓站的一些技巧总结:进阶篇 一.gzip/deflate支持现在的网页普遍支持gzip压缩,这往往可以解决大量传输时间,以VeryCD的主页为例,未压缩版本247K,压缩了以后45 ...

  7. gtk+blade+anjuta 的简单实例

    gtk+blade+anjuta 的简单实例我的系统 ubuntu 12.04   1>  选择源 不正确会有很多问题,速度慢,找不到安装的软件.163的源就不错 http://mirrors. ...

  8. 基于Linux根据僵尸网络病毒平台《比尔盖茨》

    感觉分析的非常好,所以决定翻译出来,希望和大家多多交流O(∩_∩)O~ 转载请注明出处:http://blog.csdn.net/u010484477     O(∩_∩)O谢谢 keyword:病毒 ...

  9. 理解Spring的Bean工厂

    一提到工厂,我们先来回顾前面学习过的工厂方法和抽象工厂模式: 工厂方法:针对产品维度,能够产生新的产品,也能够产生新的产品工厂,既能够扩展产品维度.可是假设我们想在普通工厂上生产产品系列,就会特别麻烦 ...

  10. POJ 3267-The Cow Lexicon(DP)

    The Cow Lexicon Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8252   Accepted: 3888 D ...