函数表达式

一、闭包

概念:闭包是指有权访问另一个函数作用域中变量的函数。

        function createCompareFun(propertyName) {
return function (obj1, obj2) {
var a = obj1[propertyName];
var b = obj2[propertyName]; if (a < b) {
return -1;
}
if (a > b) {
return 1;
} else {
return 0;
}
}
} //创建匿名函数
var compare = createCompareFun("age");
//调用该函数
var result = compare({age:3},{age:8});
console.log(result); //-1

如果一个闭包能访问的函数被执行完毕,作用域链(本质上是一个指向变量对象的指针列表)被销毁后,

其活动对象也不会被销毁,因为它们被闭包引用,知道闭包函数被销毁后,它们才被销毁。

由于闭包会携带包含它函数的作用域,所以会占用更多内存,建议能不使用闭包就不要使用闭包。

作用域链的这种配置机制引出了另外一个重要问题:闭包只能取得包含函数中任何一个变量的最后一个值。

        function createFun() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function () {
return i;
}
}
return result;
}; function getResult(fun, array) {
for (var j = 0; j < fun.length; j++) {
array[j] = fun[j]();
}
return array;
} var fun = createFun();
var array = new Array();
var a = getResult(fun,array);
console.log(a); //[ 10, 10, 10, 10, 10, 10, 10, 10, 10, 10 ]

注意该问题的本质:注意函数实际执行时i变量的值,定义时的值不能说明问题。

解决办法:

        function createFun() {
var result = new Array();
for (var i = 0; i < 10; i++) {
result[i] = function (num) {
return function () {
return num;
};
}(i);
}
return result;
}; /*var b = function rightNow(a) {
return a;
}(5);
console.log(b);*/

闭包中this的问题:

        var name = "Window";
var obj = {
name: "Object",
getFun: function () {
return function () {
return this.name;
};
}
};
console.log(obj.getFun()()); //Window //解决:
var obj2 = {
name: "Obj2",
getFun: function () {
console.log("Fun's name: "+this.name);
var v = this.name;
return function () {
return v;
}
}
}
console.log(obj2.getFun()());
        var name = "Window";
var obj = {
name: "Object",
getFun: function () {
return this.name;
}
}; var a = obj.getFun;
console.log(a()); //Window
console.log(obj.getFun()); //Object

内存泄漏问题:

        window.onload = function () {
function outer() {
var element = document.getElementById("testId");
element.onclick = function () {
//闭包的作用域链中保存了一个html元素
//只要匿名函数存在,element的引用数最少是1,因此它所占用的内存永远不会被回收。
console.log(element.id);
};
}
outer(); //解决
function outer2() {
var element = document.getElementById("testId");
var id = element.id;
element.onclick = function () {
console.log(id);
};
//闭包会引用包含函数的整个活动对象,闭包即使不直接引用element,
//包含函数的活动对象任然会保存一个引用,所以这步必须有
element = null;
}
}

二、模仿块级作用域

ECMAScript很操蛋地没有块级作用域:

        function Afun() {
for (var i = 0; i < 10; i++){
console.log(i);
}
//在外面重新声明i,并没有什么卵用
var i;
console.log("Outer i is "+i);
}
Afun(); //Outer i is 10
        function Afun() {
for (var i = 0; i < 10; i++){
console.log(i);
}
//
var i = 100;
console.log("Outer i is "+i);
}
Afun(); //Outer i is 100

可以用匿名函数来模仿块级作用域:

        function Afun() {
//由于函数声明后不能直接跟员括号来执行它
//所以我们用()包裹函数声明把它转换一个指向函数的引用
(function () {
for (var i = 0; i < 10; i++){
console.log(i);
}
})();
console.log(i); //导致Error:i is not defined.
}

这种技术经常被用来限制在全局作用域中添加过多的变量和函数。

三、私有变量

私有变量:函数的参数、局部变量和在函数内部定义的函数。

共有方法 ==  特权方法

        //在构造函数定义特权方法
function MyObject() {
//私有变量
var v = 10;
//私有函数
function f() {
return false;
} //特权方法
this.pm = function () {
++v;
return v;
}
} var o = new MyObject();
//除了pm()没有任何途径能访问到真正的o.v
console.log(o.v); //undefined
o.v = 166;
//假的
console.log(o.v); //
console.log(o.pm()); //

一)静态私有变量

也可以通过在私有作用域中定义私有变量和函数,创建特权方法。

        (function () {
var v = 10;
function f() {
return false;
} //注意这里没有var,是全局的
//为了保证全局,也没有使用声明函数
MyObject = function () {
}; MyObject.prototype.pm = function () {
v++;
return f();
};
})(); console.log(MyObject);
console.log(new MyObject().pm()); //false

JavaScript基础笔记(五) 函数表达式的更多相关文章

  1. JavaScript基础笔记一

    一.真假判断 真的:true.非零数字.非空字符串.非空对象 假的:false.数字零.空字符串.空对象.undefined 例: if(0){ alert(1) }else{ alert(2) } ...

  2. JavaScript基础笔记二

    一.函数返回值1.什么是函数返回值    函数的执行结果2. 可以没有return // 没有return或者return后面为空则会返回undefined3.一个函数应该只返回一种类型的值 二.可变 ...

  3. JavaScript基础笔记集合(转)

    JavaScript基础笔记集合   JavaScript基础笔记集合   js简介 js是脚本语言.浏览器是逐行的读取代码,而传统编程会在执行前进行编译   js存放的位置 html脚本必须放在&l ...

  4. javascript立即调用的函数表达式N种写法(第二篇)

    原文:javascript立即调用的函数表达式N种写法(第二篇) 上一篇博客我谈到将函数声明转换为函数表达式最常见的一种写法是:通过括号()将匿名函数声明转换为函数表达式即(function(){}) ...

  5. 《JavaScript高级程序设计》笔记:函数表达式(七)

    递归 function factorial(num){ if(num<=1){ return 1; }else { return num * arguments.callee(num-1); } ...

  6. JS学习笔记 (五) 函数进阶

    1.函数基础 1.1 函数的基本概念 函数是一段JavaScript代码,只被定义一次,但是可以被调用或者执行许多次.函数是一种对象,可以设置属性,或调用方法. 函数中的参数分为实参和形参.其中,形参 ...

  7. 理解JavaScript的立即调用函数表达式(IIFE)

    首先这是js的一种函数调用写法,叫立即执行函数表达式(IIFE,即immediately-invoked function expression).顾名思义IIFE可以让你的函数立即得到执行(废话). ...

  8. JavaScript基础笔记(三) 引用类型

    引用类型 引用类型的值(对象)是引用类型的一个实例. 一.Object类型 创建Object实例: //方法一:通过new操作符创建 var a = new Object(); a.neme = &q ...

  9. JavaScript基础知识(函数)

    函数的基础 函数: 把实现相同功能的代码放到一个函数体中,当想实现这个功能时,直接执行这个函数即可:减少了的冗余:高内聚,低耦合--> 函数的封装: 函数:引用数据类型: var a = 10; ...

随机推荐

  1. markdown 相关零碎知识

    1.尖括号<>在markdown会被当做html符号,解决办法:用转义字符,如:<测试>  可以写作&lt:测试>

  2. 如何使用Scrapy框架实现网络爬虫

    现在用下面这个案例来演示如果爬取安居客上面深圳的租房信息,我们采取这样策略,首先爬取所有租房信息的链接地址,然后再根据爬取的地址获取我们所需要的页面信息.访问次数多了,会被重定向到输入验证码页面,这个 ...

  3. POJ 1064 Cable master (二分法+精度控制)

    Cable master Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 65358   Accepted: 13453 De ...

  4. gradle repo conf - maven-central.storage-download.googleapis.com

    repositories { google() jcenter() maven { // The google mirror is less flaky than mavenCentral() url ...

  5. 最新版谷歌浏览器的Flash设置已经不能保存了?

    解决方法:先去chrome实验室界面chrome://flags/#enable-ephemeral-flash-permission选择取消Disabled.取消该实验室选项. 然后去chrome: ...

  6. file /usr/share/mysql/charsets/README from install of MySQL-server-5.1.73-1.glibc23.i386 conflicts with file from package mysql-libs-5.1.73-8.el6_8.i686

    1:也许之前的机器安装过Mysql,但是自己不知道,账号密码也忘记了,又执行安装操作,导致Mysql不兼容问题.Linux上安装MySQL时出现不兼容的解决办法,错误如下所示: [root@maste ...

  7. 利用 Windows API Code Pack 修改音乐的 ID3 信息

    朋友由于抠门 SD 卡买小了,结果音乐太多放不下,又不舍得再买新卡,不得已决定重新转码,把音乐码率压低一点,牺牲点音质来换空间(用某些人的话说,反正不是搞音乐的,听不出差别)… 结果千千静听(百度音乐 ...

  8. [转] 浅谈session,cookie,sessionStorage,localStorage的区别及应用场景

    浏览器的缓存机制提供了可以将用户数据存储在客户端上的方式,可以利用cookie,session等跟服务端进行数据交互. 一.cookie和session cookie和session都是用来跟踪浏览器 ...

  9. python词云

    词云图 from os import path from PIL import Image import numpy as np import matplotlib.pyplot as plt fro ...

  10. Python 面向对象1-面向对象介绍

    一.无论用什么形式来编程,我们都要明确记住以下原则: 1.写重复代码是非常不好的低级行为 2.你写的代码需要经常变更,写代码一定要遵循易读,易改的原则 3.函数编程与OOP(面向对象)的主要区别就是O ...