《JS权威指南学习总结--8.5 作为命名空间的函数》
内容要点:
函数作用域的概念:在函数中声明的变量在整个函数体内都是可见的(包括在嵌套的函数中),在函数的外部是不可见的。不在任何函数内声明的变量是全局变量,在整个JS程序中都是可见的。
在JS中无法声明只在一个代码块内可见的变量的。(在客户端JS中这种说法不完全正确,比如,在有些JS的扩展中就可以使用let来声明语句块内的变量)
基于这个原因,我们常常简单地定义一个函数用做临时的命名空间,在这个命名空间内定义的变量是都不会污染到全局命名空间。
比如,假设你写了一段JS模块代码,这段代码将要用在不同的JS程序中(对于客户端JS来讲通常是用在各种各样的网页中)。和大多数代码一样,假定这段代码定义了一个用以存储中间计算结果的变量。这样问题就来了,当模块代码放到不同的程序中运行时,你无法得知这个变量是否已经创建了,如果已经存在这个变量,那么将会和代码产生冲突。
解决方法是:将代码放入一个函数内,然后调用这个函数。这样全局变量就变成了函数内的局部变量。
一.定义匿名函数并立即在单个表达式中调用
(function(){
//模块代码
}()); //结束函数定义并立即调用它
这种定义匿名函数并立即在单个表达式中调用它的写法非常常见,已经成为一种惯用法了。
下例中,展示了这种命名空间技术。它定义了一个返回extend()函数的匿名函数,此匿名函数中的代码检测了是否出现一个众所周知的IE bug,如果出现了这个bug,就返回一个带补丁的函数版本。此外,这个匿名函数命名空间用来隐藏一组属性名。
例:
//特定场景下返回带补丁的extend()版本
//定义一个扩展函数,用来将第二个以及后续参数复制至第一个参数
//如果o的属性拥有一个不可枚举的同名属性,则for/in循环不会枚举对象o的可枚举属性,也就是说,将不会正确地处理诸如toString的属性,除非我们显式检测它
var extend = (function(){ //将这个函数的返回值赋值给extend
//在修复它之前,首先检查是否存在bug
for( var p in {toString:null} ){
//如果代码执行到这里,那么for/in循环会正确工作并返回
//一个简单版本的extend()函数
return function extend(o){
for(var i=1;i<arguments.length;i++){
var source = arguments[i];
for( var prop in source ) o[prop] =source[prop];
}
return o;
};
}
//如果代码执行到这里,说明for/in循环不会枚举测试对象的toString属性
//因此返回另一个版本的extend()函数,这个函数显式测试
//Object.prototype中的不可枚举属性
return function patched_extend(o){
for( var i=1;i<arguments.length;i++ ){
var source=arguments[i];
//复制所有的可枚举属性
for( var prop in source ) o[prop] = source[prop];
//现在检查特殊属性
for( var j=0;j<protoprops.length;j++ ){
prop = protoprops[j];
if( source.hasOwnProperty(prop)) o[prop] = source[prop];
}
}
return o;
};
var protoprops = ["toString","valueOf","constructor","hasOwnProperty","isPrototypeOf","propertyIsEnumrable","toLocaleString"];
}());
var h ={x:1,y:2,z:3};
var s = extend(h);
console.log(s); //Object { x=1, y=2, z=3}
console.log(s.x); //1
《JS权威指南学习总结--8.5 作为命名空间的函数》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- luogu P2580 于是他错误的点名开始了
luogu P2580 于是他错误的点名开始了 https://www.luogu.org/problem/show?pid=2580 题目背景 XS中学化学竞赛组教练是一个酷爱炉石的人. 他会一边 ...
- centos6.8 搭建nginx+uwsgi+Flask
1.安装 yum install nginx -y pip3 install uwsgipip3 install Flask 2.uwsgi配置(保存/etc/uwsgi.ini,run:uwsgi ...
- URL传值问题,不同浏览器对URL的长度要求
通过URL传值的问题,所以对url字符串进行encodeURIComponent对url字符串内容进行编码,问题解决,但是有时候会出现 The request filtering module is ...
- Linux sendmail 详解
Internet上最基本的服务,现在应该大部分人都有自己的邮箱吧,用的人多,但理解的人估计没多少,我自己以前也是常常用,但对其原理并不操心.今天就来操心下,进行个小总结 一.邮件服务的基本流程 ...
- Ajax与CustomErrors的尴尬
在ASP.NET程序中,为了给用户显示友好的错误信息,通常在web.config中进行如下的设置: <customErrors mode="RemoteOnly" defau ...
- 使用log4cxx在GUI 程序中将信息输出到Console
之前看到有个方法是在项目属性设置里实现的 以VS2010为例: 右键Project选择Properties->Configuration Properties->Build Events- ...
- 详解 UIView 的 Tint Color 属性
在iOS 7后,UIView新增加了一个tintColor属性,这个属性定义了一个非默认的着色颜色值,其值的设置会影响到以视图为根视图的整个视图层次结构.它主要是应用到诸如app图标.导航栏.按钮等一 ...
- ios下iphone的plus下
二维码能被长按识别,但因为某种原因识别区域发生了偏移 meta标签定义了默认缩放为一倍就能识别,不定义就不能识别. 网上是这么说的: meta标签定义了默认缩放为一倍就能识别,不定义就不能识别.于是我 ...
- DB2数据库实例创建与删除 学习笔记
以root身份执行 $DB2HOME/instance/db2idrop -f 实例名,注意一定要加-f,否则不会删除实例下面sqllib文件.如果不幸忘了,执行db2icrt,会报sqllib文件存 ...
- C#项目间循环引用的解决办法,有图有真相
C#项目间循环引用的解决办法,有图有真相 程序间的互相调用接口,c#禁止互相引用,海宏软件,20160315 /// c#禁止互相引用,如果项目[订单]中有一个orderEdit单元,要在项目[进销存 ...