匿名函数自执行原理和instanceof运算符执行原理
今天收到RSS订阅中有一篇《Javascript – Arraylike的7种实现》,看第一种实现方式是,瞬间被!function(){}()这种匿名函数自执行方式给亮瞎了眼睛。这种写法绝对是装逼神器,代码如下:
!function () {
//通过闭包实现
var List = function () {
var list = [],
self = {
constructor: List,
//如果希望更像原生一点,将length定义为属性,那么length则需要自己维护
length: function () { return list.length; },
add: function (item) {
list.push(item);
},
eq: function (index) {
return list[index];
}
};
return self;
};
//测试
console.group('第一种 - 通过闭包实现');
var demo = new List();
demo.add('List - add()');
console.log('demo instanceof List : %c' + (demo instanceof List), 'color:red;');
console.log('demo.constructor === List :%c' + (demo.constructor === List), 'color:blue');
//无法通过索引demo[0]这种方式访问
console.log('成员:[ ' + demo.eq(0) + ' , ' + demo.eq(1) + ' ]');
console.log('length:' + demo.length());
//注意看demo对象
console.log(demo);
console.groupEnd();
}();
其实-function(){}();+function(){}();~function(){}()这些也可以实现匿名函数的自执行,其原理就是当function(){}()前面有一个运算符时,js解释器在“看到”运算符后,会在后面继续寻找用于计算的值function(){},然后执行这个函数得到用于运算的值。在进行取反或加之类的运算时,由于js会将除null,undefined,0等个别的数转换为boolan值中的false,其它的字符串,对象函数都会转换为true,所以对函数进行一次取反运算不会抛出异常,也不会改变这个函数。同理,进行加运算也是一样,js会把对象和函数尝试转换为数字,得到NaN而不会抛出异常。这个可以使用如下代码进行验证:
console.log(!function () {
console.log(1);
}) ; //只会打印出false,不会打印出1
console.dir(-function () {
console.log(1);
}); //只会打印出NaN
很明显,使用?function(){}()会比使用(function(){})()多一次运算过程。当js解释器知道function(){}是个函数后,在其后面加一个括号,则其调用这个函数,其是这和将function(){}赋值给一个变量a,然后使用a()调用一样。那么为什么不能直接使用function(){}()调用呢?其实我们可以看这样调用在chrome中报的错: Uncaught SyntaxError: Unexpected token ( ,这和写function()报出的错误一样。可以发现,js解释器将function(){}()解析成了function();{}();为什么会解析成这样呢?还有就是为什么写成(function(){}())也可以正确执行呢?我们可以去看看函数的定义,在《javascript权威指南第6版》中对于函数的定义这样写道:函数使用function关键字来定义,它可以用在函数定义表达式或者函数声明语句里。函数定义表达式的语法为var functionName = function(){};函数声明语句语法为function funcname(){};所以,如果不写括号,javascript解释器会试图将关键字function解析为函数声明语句(同理用于运算的值只能是表达式和不能是声明语句)。在function前面使用了圆括号,则javascript解释器才会正确地将其解析为函数定义表达式(匿名)。这样就可以指定,Unexpected token ( 错误是因为expect 函数名。
instanceof
我们再来看看最上面代码的22行,
demo instanceof List =====> false
其实很简单,因为List有返回值,所有var demo = new List();其实等价于var demo = List(); 所有demo并不是List的实例。在来看看instanceof的定义:
instanceof运算符希望左操作数是一个对象,有操作数标识对象的类。如果左侧的对象是右侧类的实例,则表达式返回true;否则返回false。JavaScript中对象的类是通过初始化它们的构造函数来定义的。这样的话,instanceof的右操作数应当是一个函数,如果右操作数不是函数,则抛出一个类型错误异常。注意,所有的对象都是Object的实例。
function Person(){
this.name = 'xt';
this.get = function(){
return "xt1";
}
}
var p = new Person();
var List = function(){
var list = [],
self = {
constructor: List,
//如果希望更像原生一点,将length定义为属性,那么length则需要自己维护
length: function () { return list.length; },
add: function (item) {
list.push(item);
},
eq: function (index) {
return list[index];
}
};
return self;
};
var li = new List();
console.log(p.__proto__ === Person.prototype); //true
console.log(li.__proto__ === List.prototype); //false function inherit(p){
function f(){}
f.prototype = p;
return new f();
}
var student = inherit(p); //student对象继承p对象。 console.log(student.__proto__ === Person.prototype); //false
console.log(student.__proto__.__proto__ === Person.prototype); //true
匿名函数自执行原理和instanceof运算符执行原理的更多相关文章
- JavaScript 函数声明,函数表达式,匿名函数的区别,深入理解立即执行函数(function(){…})()
function fnName(){xxxx}; // 函数声明:使用function关键字声明一个函数,在指定一个函数名. //例如:(正常,因为 提升 了函数声明,函数调用可以在函数声明之前) f ...
- Javascript的匿名函数与自执行
1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没有函数名的函数. 1.1 函数的定义,首先简单介绍一下函数的定义,大致可分为三种方式 第一种: ...
- JS执行顺序-函数声明提升、匿名函数、函数表达式
大方向上: JS 是按照 代码块 进行 编译.执行 的. 学习至: 1.变量声明提升 2.新唐的博客 3.js中匿名函数的创建与调用方法分析 4.前端圣经 - <高程三> 5.深入理解变量 ...
- JavaScript(第十五天)【匿名函数和闭包】
学习要点: 1.匿名函数 2.闭包 匿名函数就是没有名字的函数,闭包是可访问一个函数作用域里变量的函数.声明:本节内容需要有面向对象和少量设计模式基础,否则无法听懂.(所需基础15章的时候已经声明 ...
- Python之路(第七篇)Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数
一.作用域 return 可以返回任意值例子 def test1(): print("test1") def test(): print("test") ret ...
- Python之路Python作用域、匿名函数、函数式编程、map函数、filter函数、reduce函数
Python之路Python作用域.匿名函数.函数式编程.map函数.filter函数.reduce函数 一.作用域 return 可以返回任意值例子 def test1(): print(" ...
- python基础-匿名函数、内置函数、正则表达式、模块
1. 匿名函数 1.1 有名函数 有名函数:定义了一个函数名,函数名指向内存地址:通过函数名进行访问.函数名加括号就可以运行有名函数,例如:func() def func(x, y, z = 1): ...
- php匿名函数与闭包函数
匿名函数:没有名字的函数:并没有牵扯到应用其他函数的变量问题.仅仅是没有名字 $f=function($param){} 闭包:A函数中嵌套着B函数,B程序中有用到A的变量,当外部函数C调用函数A时, ...
- 【转】javascript变量作用域、匿名函数及闭包
下面这段话为摘抄,看到网上大多数人使用的是变量在使用的时候声明而不是在顶端声明,也可能考虑到js查找变量影响性能的问题,哪里用就在哪里声明,也很好. 在Javascript中,我们在写函数的时候往往需 ...
随机推荐
- VS2010/MFC编程入门之五(MFC消息映射机制概述)
VS2010/MFC编程入门之五(MFC消息映射机制概述)-软件开发-鸡啄米 http://www.jizhuomi.com/software/147.html 上一讲鸡啄米为大家简单分析了MFC应用 ...
- swift:创建集合视图UICollectionView
swift中创建集合视图和OC中差不多,主要是实现UICollectionViewDataSource数据源协议和UICollectionViewDelegateFlowLayout自定义布局协议,其 ...
- Android 获取屏幕高度,宽度,状态栏高度
背景介绍: 到目前为止,android已经从1.5发展到目前的3.2,我们在写一个应用的时候,最常用到得就是获取屏幕高度,宽度,以及status bar的高度. 然而android系统变化太快了,从开 ...
- jquery的extend和fn.extend的使用说明
jQuery.fn.extend(object); 对jQuery.prototype进得扩展,就是为jQuery类添加“成员函数”.jQuery类的实例可以使用这个“成员函数”. jQuery为开发 ...
- Win API 内存整理
记得我的笔记本上曾经安装了一款名为内存整理大师的软件,当时觉得挺好用而且挺NB的,就是导致开机启动有点慢. 当时我就在想,内存整理是怎么实现的?不过那是水平实在是不怎么样,估计连windows程序的消 ...
- asp开发微信扫码支付
这个任务已经给了.现在正在学习开发中.主要注意的是2点. 1:返回参数的验证. 2:通知后业务处理和处理后返回财付通.大部分操作,api中已经处理好. 现在需要的业务逻辑部分. 需要正确3个参数 r ...
- Mac AppStore下载文件的获取
有时候希望把在mac AppStore下载的App共享给其他人,但是application里面的都是已经安装的应用,那么如何找到pkg安装文件呢? (后附:注意事项!) 方法一: 1.首先下载一个Ap ...
- MTK6515 android打版软件配置(DrvGen.exe 使用)
1 一.配置GPIO 2 二.配置emmc 3 三.配置LCM 3.1 1.增加LCM驱动文件 3.2 2.配置驱动文件 3.3 3.配置背光 4 四.配置touch panel 4.1 1.通过dc ...
- 同步synchronized用法
今天在高人的指导下,对同步synchronized用法有了更高一层的理解,非常感谢他的无私奉献.在此把代码贴出来方便日后查阅. publicclass SfServlet { privatestati ...
- Ajax的简单请求案例
$.ajax({ url : rootPath +'/jasframework/choosepilecontrol/querySubsytem.do', type : "POST" ...