私人定制javascript中函数小知识点
函数的定义
首先在javascript中,函数就是对象,程序可以随意操控它们。比如,可以给它们设置属性,甚至调用它们的方法。函数使用function关键字来定义。它既可以用在函数定义表达式,也可以用在函数声明语句中。函数声明function后面必须要更上函数名称也就是所谓的函数名称标识符。如果是函数表达式函数名称标识符可有可无。这段重点是函数是对象,所以函数表现出来的种种行为你想想成对象,那么很多疑惑可能就恍如昨日初见。
函数调用
4种方式来调用javascript函数:
1.作为函数
就是函数名称后加上圆括号加上参数列表 例如 func(2,3); 这里需要说明的是如果函数里有没有return obj;那么改函数返回值都是undefined除非返回就是undefined值。每个函数都有默认的返回值undefined;除非给予返回值。
2.作为方法
如果一个对象的属性被赋值为一个函数表达式,那么该函数就被当作一个方法,而不是作为一个普通函数来调用了。
例如:o.m=f; o.m();
3.作为构造函数
如果函数或方法调用之前带有关键字new,它就是构造函数调用,构造函数调用和普通的函数调用以及方法调用在实参处理,调用上下文和返回值方面都有不同。 构造函数通常不会使用return关键字,它们通常初始化新对象。
4.通过它们的call()和apply()方法间接调用
再次强调javascript中的函数也是对象,和其他javascript对象一样,函数对象也可以包含方法,其中每个函数都都有两个很熟悉不过的函数call()和apply()可以用来间接地调用函数。指定上下文this值,指定参数列表。后者传入参数时需要按照数组的形式传入参数。
函数的实参对象
如果在调用方法时少传参数,那么其余参数都将置为undefined。那么如何知道到底传了多少参数呢,实际的参数到底是多少个呢?在函数体内,标识符arguments就是指向实参对象的引用,实参对象视一个类数组对象。
例如
function f(x,y,z)
{
if(arguments.length!=3){
throw new Error(“arguments length is should be 3”);
}
}
arguments.length是指实参个数,而f.length是指形参的个数
callee和caller属性
callee属性指代当前正在执行的函数,caller可以访问调用栈
浅说闭包
现在不得不扯到闭包,javascript采用词法作用域,就是说函数的执行依赖于变量作用域,这个作用域是在函数定义时决定的,而不是函数执行时决定的。为了实现这种词法作用域,javascript函数对象的内部状态不仅包含函数逻辑代码,还必须引用当前的作用域链。函数对象可以通过作用域链相互关联起来,函数体内部的变量都可以保存在函数作用域内,这种特性就叫做闭包。函数定义时的作用域链在调用函数时依然有效,但是这并不影响闭包。
首先上一段简单的代码:
var scope=”global scope”;
function f(){
var scope=“local scope”;
function func(){return scope;}
return func();
}
console.log(f()); //”local scope“
简单解释一下,关键是变量scope在函数func定义的时候就在同一个作用域链中,而var scope=”global scope”;是在最外层的作用域中,一般都在作用域中都会存在一个变量对象来专门存放作用域链,全局变量肯定是最先被存放就进去,即压入栈底,而此时在执行调用func就会找最近的变量scope找到了,立马返回。所以就会是local scope不知道我的语言组织你能明白么?
var scope=”global scope”;
function f(){
var scope=“local scope”;
function func(){return scope;}
return func;
}
console.log(f()());
请问结果是多少?
这个时候将javascript词法作用域的基本规则体现的很淋漓尽致,javascript函数执行用到了作用域链,这个作用域链式函数定义的时候创建的。嵌套的函数func()定义在这个作用域链里,其中变量scope一定是选取最近的局部变量,不管任何时候执行func(),这种绑定在执行func()时依然有效,因此返回为”local scope”. 多个函数共享一个作用域
function counterfun(){
var n=0;
return{
count:function(){return n++;},
reset:function(){return n=0;}
};
}
var c=counterfun(),d=counterfun();
console.log(c.count()); //0
console.log(c.reset()); //0
console.log(d.count()); //0
console.log(c.reset()); //0
console.log(d.count());//
分析:因为函数count和reset共享一个属性,所以如果c.count()和c.reset()都会改变n的值并且相互影响,但是影响不了d.count()和d.reset()因为它们创建了各自独立的作用域链。 但是为什么n的值会被保存下来呢?此时你再回过头看看scope变量的那个例子道理一样,用return返回函数时都已经将私有变量保存起来了,下次再执行时肯定还是取这段作用域中的变量来操作。
易出错且经典的例子
如下:
function constfuncs(){
var funcs=[];
for(var i=0;i<10;i++)
funcs[i]=function(){return i;};
return funcs;
}
var funcs=constfuncs();
console.log(funcs[5]());//输出是什么呢?
这个应该不会出错吧。必须是10,因为这里所有的函数funcs[i]都共享一个作用域链其中变量i同样是共享。所以最终是循环结束的最大值10 那接下来的这个呢?
function constfunc(v){return function(){return v;};}
var funcs=[];
for(var i=0;i<10;i++) funcs[i]=constfunc(i);
console.log(funcs[5]());//输出是什么呢?
输出是5,结果是我们预期的。 这里如果按照所有的函数作用域是定义的时候就确定了的,理解起来比较费劲么,不管你信不信,反正我是中枪了。 从函数嵌套来理解,因为函数中返回函数嵌套时必须会将函数及其作用域链保存起来,这样就新创建了一个作用域链,其中的变量i也就被保存起来赋值给v了,每每return一次就会新创建一个作用域链。所以得到的v就是当时保存的i值。
prototype属性
每个函数都用一个prototype属性,请记住它是函的一个属性,尽管这个prototype我们总是称之为对象,但是它确实是函数的一个对象。它就称之为原型对象,不管你是否打算将这个函数作为构造函数来用。那问题来了,为啥我们要关注prototype属性呢?
1.原生构造函数(如 Object()/Array()/Function()等)使用prototype属性,以便让构造函数实力继承属性和方法。
2.当用户自定义构造函数时,可以像javascript原生对象那样使用继承。
3.可以借用别人编写的优秀代码的时候继承赋值过来自己用
4.通过使用原型继承,我们可以创建有效的对象实例,并且使用相同的方法,这样就节省了很多代码。
结束语
本节重点是函数是对象,所表现出来的一些特性,同时函数作用域链相关的闭包这4个例子应该是堪称经典了,以后可以经常看看,还有比较重要的作用域链等等,以后再深入了解,再继续分享。同时如果有错误,还请指出。今天看了乐嘉书中,觉得有一句话说的挺好的,我全力回顾了自己曾有的梦想,对比已实现的和没实现的,终于发现,梦想都与行动有关,不动就是幻想,动了就是梦想,动到底梦想就实现了。也许我做的梦,刚好也是你的梦,果真如此,此刻开始,你我就算是同梦中人了。如果你觉得对你有所帮助,推荐一下,给我下次写作的动力。
ps: 给大家介绍一个新词(不要问我是谁,请叫我好人)。
路见不平
旧意:指走在路上遇见不公平的事情
新意:指走在路上在一大波平胸妹子中发现一个大波妹子
例句:路见不平,拔屌想护
私人定制javascript中函数小知识点的更多相关文章
- 私人定制javascript中对象小知识点(Only For Me)
废话不多讲,先上笑话,然后再,.看懂这个的说明你的节操已经不再了. 晚饭后去理发店理发...割了吧...老板问我怎么剪,我悠悠的来一句往帅了剪...高潮往往令人想不到....旁边一在焗油烫头发的大妈说 ...
- 私人定制javascript中数组小知识点(Only For Me)
先上笑话,1.刚看到一个游泳的,想起公司组织去三亚旅游,老板跳海里,各种挣扎,捞上来老板第一句话:我记得我会游泳的啊. 2.媳妇说:老公对不起,我把你新买的自行车撞散架了! 老公:没事宝贝,你若安好, ...
- Javascript中函数的四种调用方式
一.Javascript中函数的几个基本知识点: 1.函数的名字只是一个指向函数的指针,所以即使在不同的执行环境,即不同对象调用这个函数,这个函数指向的仍然是同一个函数. 2.函数中有两个特殊的内部属 ...
- 私人定制自己的linux小系统
私人定制自己的linux小系统 一.前言 linux操作系统至1991.10.5号诞生以来,就源其开源性和自由性得到了很多技术大牛的青睐,每个linux爱好者都为其贡献了自己的一份力,不管是在 ...
- JavaScript中函数的调用!
JavaScript中函数的调用! 1 普通函数 // 1 普通函数 function fn() { console.log(123); } // 函数名 + 一个小括号! 或者 函数名.call() ...
- JavaScript中函数的定义!
JavaScript中函数的定义! 1 自定义函数(命名函数) function fun() {}; 2 函数表达式(匿名函数) var fun = function () {}; 3 利用 new ...
- JavaScript中函数函数的定义与变量的声明<基础知识一>
1.JavaScript中函数的三种构造方式 a.function createFun(){ } b.var createFun=function (){ } c.var createFun=new ...
- JavaScript中函数的形参和实参的实现原理剖析
我们都知道JS里面参数的传递是可以不一样的,比如我们有一个函数: <script type="text/javascript"> function one(a,b,c) ...
- JavaScript apply函数小案例
//回调函数1 function callback(a,b,c) { alert(a+b+c); } //回调函数2 function callback2(a,b) { alert(a+b); } / ...
随机推荐
- 利用__index和__newindex实现默认值表、监控表、只读表(转)
__index和__newindex实际上相当于是在读写表的时候分别加了一道过滤的逻辑,让读写表的操作可以被监控或说回调,利用这个特性可以实现一些带有特殊功能的表. 带有默认值的表: setdefau ...
- chrome(转)
阅读目录 Chrome的隐身模式 Chrome下各种组合键 Chrome的about指令 chrome://accessibility 查看浏览器当前访问的标签 chrome://appcac ...
- HDU 1274 展开字符串 (递归+string类)
题目链接:HDU 1274 展开字符串 中文题. 左括号进入DFS函数,右括号return到上一层. 注意return回去的是这个一层递归中的括号中的字母串. AC代码: #include<st ...
- Intent用法
Intent是android系统中的最佳男主角,Intent翻译成中文的意思是"意图",说白了就是"我想要...",也就是说眼下运行中的Activity想要请其 ...
- CCProgressTo 和CCProgressTimer
在cocos2d中相同提供了非常多表现图片和精灵的方式,上一篇其中提到的切换场景的方式之中的一个是顺或逆时针切入的方法,在图片上也能够使用,test里有一个样例介绍CCProgressTimer能够实 ...
- MailTest
GridBagLayout把一个界面分为m行n列的网格 GridBagConstraints的一个实例:gridx = 2; // X2,表示组件位于第2列gridy = 0; // Y0,表示组件位 ...
- 【转】Android 收集已发布程序的崩溃信息
我们写程序的时候都希望能写出一个没有任何Bug的程序,期望在任何情况下都不会发生程序崩溃.不过理想是丰满的,现实是骨感的.没有一个程序员能保证自己写的程序绝对不会出现异常崩溃.特别是针对用户数达到几十 ...
- 关于sql中去换行符的问题
今天要用bootstrap开发一个网页,要使用到JSON,但是JSON的格式不正确,然后在http://www.bejson.com/[Be JSON]中测试了一下JSON. 发现JSON中多了一个换 ...
- git常用命令学习(转)
一.Bug分支 1,假设如下场景,你正在dev分支工作,突然接到一个修复代号为101的bug的任务时,dev的东西还没不能提交,但是bug需要马上修复. Git提供了一个stash功能,可以把当前工作 ...
- Data URI(转)
Data URL 早在 1995 年就被提出,那个时候有很多个版本的 Data URL Schema 定义陆续出现在 VRML 之中,随后不久,其中的一个版本被提上了议案——将它做个一个嵌入式的资源放 ...