博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《JavaScript高级程序设计》笔记:函数表达式(七)
阅读量:5147 次
发布时间:2019-06-13

本文共 5512 字,大约阅读时间需要 18 分钟。

递归

function factorial(num){    if(num<=1){        return 1;    }else {        return num * arguments.callee(num-1);    }}console.log(factorial(4));

但是如果代码是在严格模式下开发:

"use strict";function factorial(num){    if(num<=1){        return 1;    }else {        return num * arguments.callee(num-1);    }}console.log(factorial(4));

结果:Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them

在严格模式下不能通过脚本访问arguments.callee,访问这个属性会报错,那么可以使用命名函数表达式来达到相同的结果:

"use strict";var factorial = (function f(num){     if(num<=1){        return 1;    }else {        return num * f(num-1);    }})console.log(factorial(4)); //24

以上代码创建了一个名为f()的命名函数表达式,然后将它赋值给变量factorial,即是把函数赋值给另外一个变量,函数的名字仍然有效。

闭包

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

闭包与变量

作用域链的这种配置机制引出了一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。别忘了闭包所保存的是整个变量对象,而不是某个特殊的变量。

function createFunctions(){    var result = new Array();    for (var i=0; i<10; i++){        result[i] = function(){            return i;        }    }    return result;}

我们可以通过创建另一个匿名函数强制让闭包的行为符合预期。

function createFunctions(){    var result = new Array();    for (var i=0; i<10; i++){        result[i] = function(num){            return function(){                return num;            };        }(i);    }    return result;}

关于this对象

在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。不过,匿名函数的执行环境具有全局性,因此其this对象通常指向window。

var name = "The window";var object = {    name: "My Object",    getNameFunc: function(){        return function(){            return this.name;        };    }};console.log(object.getNameFunc()()); // The window

不过,把外部作用域中的this对象保存在一个闭包能够访问到的变量里,就可以让闭包访问该对象了。

var name = "The window";var object = {    name: "My Object",    getNameFunc: function(){        var that = this;        return function(){            return that.name;        };    }};console.log(object.getNameFunc()()); // My Object

看下面代码:

var name = "The window";var object = {    name: "My Object",    getName: function(){        console.log(this.name);    }}object.getName(); // My Object (object.getName)(); // My Object (object.getName = object.getName)(); // The window

来分析下调用的结果:

第一行代码跟平常一样调用了object.getName()返回了My Object ,因为this.name就是object.name。

第二行代码在调用这个方法之前给它加了一个括号。虽然加了一个括号后,就好像只是在引用一个函数,但是this的值得到了维持,因为object.getName(object.getName)的定义是相同的。

第三行代码先执行了一条赋值语句,然后再调用赋值后的结果。因为这个赋值表达式的值是函数本身,所以this的值不能得到维持,结果就返回了The window

当然你不大可能像第二行和第三行代码一样调用这个方法。这个例子只是说明了一个细微的语法变化,都有可能意外的改变this的值。

内存泄露

function assignHandler(){                var element=document.getElementById('someElement');                element.onclick=function(){                    alert(element.id);                }            }

上述代码它所占用的内存不会永远消失。修改一下代码如下解决:

function assignHandler(){        var element = document.getElementById('someElement');        var id = element.id;        element.onclick = function(){            alert(id);        }        element = null;    }

模仿块级作用域

用块级作用域(通常称为私用作用域)的匿名函数的语法如下所示:

(function(){})();

私有变量

function add(num1,num2){    var sum=num1+num2;    return sum;}

在这个函数内部,有三个私有变量:sum,num1,num2。在函数内部可以访问这几个变量。但是在函数外部则不能访问它们。如果在这个函数内部创建一个闭包,那么闭包可以通过自己的作用域链也可以访问这些变量。而利用这一点,就可以创建用于访问私有变量的公有方法。

我们把有权访问私有变量和私有函数的公有方法称为特权方法。有两种在对象上创建特权方法的方式。第一种是在构造函数中定义特权方法。基本模式如下:

function myObejct(){    //私有变量和私有函数    var privateVariable=10;    function privateFunction(){        return false;    }    //特权方法    this.publicMethod=function(){        privateVariable++;        return privateFunction();    }}

利用私有和特权成员,可以隐藏那些不应该被直接修改的数据,例如:

function Person(name){    this.getName=function(){        return name;    }    this.setName=function(value){        name=value;    }}var person=new Person("Nicholas");alert(person.getName());//Nicholasperson.setName("Greg");alert(person.getName());//Greg

静态私有变量

通过在私有作用域中定义私有变量或函数,同样也可以创建特权方法。其基本模式如下:

(function(){    //私有变量和私有函数    var privateVariable=10;    function privateFunction(){        return false;    }    //构造函数    MyObject=function(){    };    //公有/特权方法    MyObject.prototype.publicMethod=function(){        privateVariable++;        return privateFunction();    }    })();

再看一个例子:

(function(){    var name = "";    Person = function(value){        name = value;    };        Person.prototype.getName = function(){        return name;    };    Person.prototype.setName = function(value){        name = value;    };})();var person1 = new Person("Nicholas");console.log(person1.getName()); //Nicholasperson1.setName('Grey');console.log(person1.getName()); //Greyvar person2 = new Person("Michael");console.log(person1.getName()); //Michaelconsole.log(person2.getName()); //Michael

在一个实例上调用setName()会影响所有的实例。

模块模式

模块模式是为单例创建私有变量和特权方法。所谓单例,指的就是只有一个实例的对象。按照惯例,js是以对象字面量的方式来创建单例对象的。

var singleton={    name:value,    method:function(){        //这里是方法的代码    }};

模块模式通过为单例添加私有变量和特权方法能够使其得到增强。其语法形式如下:

var singleton=function(){    //私有变量和私有函数    var privateVariable=10;    function privateFunction(){        return false;    }    //特权/公有属性和方法    return {        publicProperty:true,        publicMethod:function(){            privateVariable++;            return privateFunction();        }    }}();

增强的模块模式

var singleton=function(){    //私有变量和私有函数    var privateVariable=10;    function privateFunction(){        return false;    }    //创建对象    var object=new CustomType();    //添加特权/公有属性和方法    object.publicProperty=true;    object.publicMethod=function(){        privateVariable++;        return privateFunction();    }    //返回这个对象    return object;}();

 

转载于:https://www.cnblogs.com/moqiutao/p/10107536.html

你可能感兴趣的文章
关于height,line-height导致的样式混乱的问题
查看>>
《SEO实战密码》读后一点感受
查看>>
bzoj 4815 [Cqoi2017]小Q的表格——反演+分块
查看>>
Swift 入门之简单语法(六)
查看>>
shim和polyfill有什么区别
查看>>
Failed to load the JNI shared library “E:/2000/Java/JDK6/bin/..jre/bin/client/jvm.dll
查看>>
〖Python〗-- IO多路复用
查看>>
栈(括号匹配)
查看>>
夜太美---酒不醉--人自醉
查看>>
Java学习 · 初识 面向对象深入一
查看>>
源代码如何管理
查看>>
vue怎么将一个组件引入另一个组件?
查看>>
bzoj1040: [ZJOI2008]骑士
查看>>
LeetCode 74. Search a 2D Matrix(搜索二维矩阵)
查看>>
利用SignalR来同步更新Winfrom
查看>>
反射机制
查看>>
CocoaPod
查看>>
css3实现漂亮的按钮链接
查看>>
[python基础] python 2与python 3的区别,一个关于对象的未知的坑
查看>>
BZOJ 1251: 序列终结者 [splay]
查看>>