我读汤姆大叔的深入理解js(二)

继续汤姆大叔的js之旅。

揭秘命名函数表达式

函数表达式和函数声明

  汤姆大叔在博客中引用ECMA规范:函数声明必须带有标识符,函数表达式可以省略。对于我来说这些概念的东西真是不所适从。还是大叔的实例带劲。上实例如下:

function foo(){};//鬼都知道是声明

var bar = function foo(){};//鬼也知道是表达式

new function bar(){};

(function() {

  function bar(){};//这也是声明

})();这些大家看看应该都很好理解。在这里大叔还总结了一点可以在大部分情况下快速的判断是表达式还是函数声明"赋值一定是表达式,不带函数名一定是表达式"。

还有一种函数表达式是不太常见,就是用括号括住的(function foo(){})。这个是表达式的原因很简单括号()是一个分组操作符,而更重要的是分组操作符的内部只能包含表达式。

函数语句

  虽然提到这个,但是现在可能还是存在不支持(chrome浏览器我看是支持的)(这点儿我自己没有细想也没有完全的去理解)。

命名函数表达式

  直接上实例var bar = function foo(){};这是有效的命名函数表达式,大叔特意强调新定义函数作用域内有效。看大叔的这个例子吧,看懂就理解了:

function foo(){return bar();}

var bar = (function(){

  if(window.addEventListener){

    return function bar(){

      return baz();

    };

  }

  else if(window.attachEvent){

    return function bar(){

      return baz();

    };

  }

})();

function baz(){

  debugger;

}

foo();

我们来看看这些函数调用过程:foo->bar;而bar是一个命名函数表达式,由内部的两次返回之后是baz,也就是说baz被bar调用。bar->baz;baz内部调用debugger。

  js的bug

  • 函数表达式的标识符泄露到外部的作用域;实例1
  • 将命名函数表达式同时作为函数声明和函数表达式;实例2
  • 命名函数表达式创建两个截然不同的函数对象;实例3
  • 仅仅顺序解析函数声明而忽略条件语句块;实例4

  实例1:var f = function g(){};typeof g;//“function”;亲自在IE8上测试成功。这是不应该的,标识符g被解析成函数,可能前端程序员在写程序的好多时候的bug就是这样引起的。

  实例2:var typeof g;var f = function g();同样在ie8下是function,在chrome下是undefined

  实例3:var f = function g(){};f === g;f.expando = ‘foo‘;g.expendo;测试chrome下不能运行(显示g没有定义)。

  实例4:var f = function g(){return 1;};if(false){f=function g(){return 2;};} g();测试chrome下是g没有定义。

这么多问题,其实都是把标识符作为一个函数声明了(个人理解)。

  js内存管理

  先看大叔给的实例,然后我们来理解大叔给我们带来的js内存管理这些内容。var f = (function(){if(true){return function g(){};}return function g(){};})();。在匿名函数调用返回的函数(就是带有标识符g的函数) ,然后赋值给外部的f;这个对象与返回的函数对象不是一个事情,多余的g函数就死在返回函数的闭包中。这就是内存问题的产生原因。

(个人对这里的一个备注,当匿名函数返回的函数是怎么赋值给f,这个赋值的底层是怎么一个实现)

  解决办法如下实例所示,就是人为手动断开引用。

var f = (function(){var f,g;if(true){f=function g(){};}else{f=function g(){};} g=null; return f;})();

时间: 2024-07-29 03:39:35

我读汤姆大叔的深入理解js(二)的相关文章

读汤姆大叔《深入理解javascript系列》笔记一编写高质量代码

感觉大叔的博文真的是很不错 我打算严格要求自己 按照大叔说的,这样我就会更有规范,更有思想的去工作 去写代码(一入代码深似海) 1,尽可能的少用全局变量(污染全局空间,也会和别人的代码 发生冲突造成严重的后果) ---->命名空间模式或者是函数立即自动执行. 2.不管是不是在函数内始终用var来声明变量, 例如: function sum(x, y){ result = x + y; //这里创建了一个隐式全局变量 return result; } 3.避免出现隐式变量 例如在函数中不通过var

汤姆大叔的6道js题目

汤姆大叔的6道javascript编程题题解 看汤姆大叔的博文,其中有篇(猛戳这里)的最后有6道编程题,于是我也试试,大家都可以先试试. 1.找出数字数组中最大的元素(使用Math.max函数) 1 2 3 var a = [1, 2, 3, 6, 5, 4]; var ans = Math.max.apply(null, a); console.log(ans);  // 6 这题很巧妙地用了apply,如果不是数组,是很多数字求最大值,我们知道可以这样: 1 2 var ans = Math

读汤姆大叔《JavaScript变量对象》笔记

一段简单的JavaScript代码思考 先看一段简单的代码,打印结果是??为什么why?? 从上述打印结果不难看出,在打印基本变量num.函数表达式fn.函数声明fun时,就已经知道变量num.函数表达式fn值为undefined,函数声明fun值为function 但这样会存在一个疑问?js在代码执行之前打印时(变量.函数表达式.函数声明)就存在值,那么在打印(变量.函数表达式.函数声明)之前究竟发了什么?? [答案是变量对象.执行上下文代码的2个阶段] (当然 打印在基本变量num.函数表达

根本没有“JSON“对象这回事(读汤姆大叔博文记录)

1.字面量 (1)他们是固定的值,不是变量,让你从“字面上”理解脚本. (2)字符串字面量是由双引号("")或单引号('')包围起来的零个或多个字符串组成的. (3)对象字面量是由花括号({})括起来的零个或多个对象的属性(key-value对). 2.何时是JSON,何时不是JSON JSON是设计成描述数据交换格式的,他也有自己的语法,这是语法是JavaScript的子集. {"proporty":"value"}这样的声明可能是JavaSc

深入理解JavaScript系列 --汤姆大叔

深入理解JavaScript系列文章,包括了原创,翻译,转载,整理等各类型文章,如果对你有用,请推荐支持一把,给大叔写作的动力. 深入理解JavaScript系列(1):编写高质量JavaScript代码的基本要点 深入理解JavaScript系列(2):揭秘命名函数表达式 深入理解JavaScript系列(3):全面解析Module模式 深入理解JavaScript系列(4):立即调用的函数表达式 深入理解JavaScript系列(5):强大的原型和原型链 深入理解JavaScript系列(6

汤姆大叔的博客-menu

1.汤姆大叔的博客http://www.cnblogs.com/tomxu/archive/2011/12/15/2288411.html 关键字:技术,管理,英文,吃喝玩乐,健身,慎独 2.menu 如何编写高质量的js代码例如避免全局变量,使用单变量声明,在循环中预缓存length(长度),遵循代码阅读可维护的代码意味着:可读的,一致的,可预测的,看上去就像是同一个人写的,已记录命名函数表达式的秘密 书写可维护的代码,这关系到底线(营业收入)和开发人员的幸福解决bug=1.花时间理解这个问题

汤姆大叔 javascript 系列 第20课 最后的5到javascript题目

博客链接:http://www.cnblogs.com/TomXu/archive/2012/02/10/2342098.html 原题: 大叔注:这些题目也是来自出这5个题目的人,当然如果你能答对4个及以上并且想拿高工资的话,请联系我. 找出数字数组中最大的元素(使用Match.max函数) 转化一个数字数组为function数组(每个function都弹出相应的数字) 给object数组进行排序(排序条件是每个元素对象的属性个数) 利用JavaScript打印出Fibonacci数(不使用全

看了汤姆大叔的“你真懂JavaScript吗?”的一些感慨

看了汤姆大叔的“你真懂JavaScript吗?”,里面有5道题目,我都一一作了,然后在chrome的控制台里面运行了一遍,虽然只错了一道,但还是细细读了下答案,在此总结一下,看看是否对大家对这些JavaScript底层的原理都懂了. 题目一(所有全局变量都是window的属性.变量声明提前.变量赋值不会提前) if (!("a" in window)) { var a = 1; } alert(a); 因为在JavaScript在变量声明提前的特性,所以事实上上述代码相当于下面所示:

你必须知道ASP.NET知识------关于动态注册httpmodule(对不起汤姆大叔)

一.关于动态注册的问题 很多人看过汤姆大叔的MVC之前的那点事儿系列(6):动态注册HttpModule ,其实汤姆大叔没有发现httpmodule动态注册的根本机制在哪里. 亦即:怎么动态注册?为什么能够动态注册? 汤姆大叔给了如下开篇 通过前面的章节,我们知道HttpApplication在初始化的时候会初始化所有配置文件里注册的HttpModules,那么有一个疑问,能否初始化之前动态加载HttpModule,而不是只从Web.config里读取? 答案是肯定的, ASP.NET MVC3