Javascript函数小结(二)

  1. 构造函数通常不使用return关键字,它们初始化新对象,当构造函数的函数体执行完毕时,它会显示返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值。然而如果构造函数显示地使用return语句返回一个对象,或者返回一个原始值,那么这是将忽略返回值,同时使用这个新对象作为调用结果。
  2. callee和caller:实参对象(arguments)的两个属性,在ECMAScript5严格模式中,对这两个属性的读写操作都会产生一个类型错误。前者指代当前正在执行的函数。caller是非标准的,但大多说浏览器实现了这个属性,它指代调用当前正在执行的函数的函数。callee经常用在匿名函数的递归调用上。eg:

varfactorial=function(x){

if(x<=1) return 1;

return x*arguments.callee(x-1);

}

console.log(factorial(3));

3.函数声明会在代码执行前被加载到作用域(全局作用域)中——有声明提升

函数表达式是在代码执行到那一行的时候才会定义——没有函数声明提升

function functionName(arg1,arg2){//这种方式叫做函数声明

//函数体

}

varfunctionName = function(arg1,arg2){//这种方式叫做函数表达式

//函数体

}

4.函数值传递:在js中,函数名师指向函数对象的指针,其本身就是变量,而函数也可以作为返回值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数,而且可以将一个函数作为另外一个函数,而且可以将一个函数作为另外一个函数的结果返回。

但是js中的传递方式只有一种:即所有参数都是按值传递。也就是说数字、字符串等按值传递,数组、对象等也按值传递。(虽然数组、对象等的按值传递与数字、字符串还是有所不同的。)

var v1 =[1,2,3];

var v2 ={};

var v3 ={a:123};

functionfn1(v1, v2, v3){

v1 = [1];

v2 = [2];

v3 = {a:3};

}

fn1(v1,v2, v3);

alert(v1);     // [1,2,3]

alert(v2);     // [object Object]

alert(v3.a);   // 123

观察上面的代码可以看出:v1、v2、v3都没有被改变、v1仍然是值为[1,2,3]的数组,v2是空白的对象,v3是具有值为123的属性a的对象。因为数组、对象等按值传递,是指变量地址的值。在函数内部我们为v1,v2,v3赋了值,也就是说我们把v1,v2,v3的指针的指向改变了,指向了新的数组和对象。这样内部的v1、v2、v3和外部的v1、v2、v3的联系完全断了。图解为:

由以上图解可知如果,在子函数内不改变局部变量的引用,而直接操作这些数组或对象的话,那么全局变量的值也是会改变的。eg:

var v1 =[1,2,3];

var v2 ={};

var v3 ={a:123};

functionfoo(v1, v2, v3)

{

v1.push(1);

v2.a = 2;

v3.a = 33;

}

foo(v1,v2, v3);

alert(v1);     // [1,2,3,1]

alert(v2.a);   // 2

alert(v3.a);   // 33

由此可知,虽然函数的参数是按值传递的,但数组、对象等引用类型的按值传递和数字、字符串等基本类型的按值传递还是不同的,主要表现在:

1)  数字、字符串是把值直接复制进去来实现的;

2)  数组、对象是把变量地址复制进去来实现的。

5.我们将作用域描述为一个对象列表,不是绑定的栈。每次调用Javascript函数的时候,都会为之创建一个新的对象用来保存局部变量,把这个对象添加至作用域链中。当函数返回的时候,就从作用域链中将这个绑定变量的对象删除。如果不存在嵌套的函数,也没有其他引用指向这个绑定对象,它就会被当做垃圾回收掉。如果定义了嵌套的函数,每个嵌套的函数都各自对应一个作用域链,并且这个作用域链指向一个变量绑定对象。但如果这些嵌套的函数对象在外部函数中保存下来,那么它们也会和所指向的变量绑定对象一样当做垃圾回收。但如果这个函数定义了嵌套的函数,并将它作为返回值返回或者存储在某处的属性里,这是就会有一个外部引用指向这个嵌套的函数。他就不会被当做垃圾回收,并且他所指向的变量绑定对象也不会被当做垃圾回收。

6.在函数体里,arguments.length表示传入函数的实参的个数。而函数本身的length属性则有着不同的含义。函数的length属性是只读属性,它代表函数形参的个数,可以通过arguments.length获取实参个数,通过argume.callee.length获取形参的个数

7.在ECMAScript5的严格模式中,call()和apply()的第一个实参都会变为this的值,哪怕传入的实参是原始值,甚至是null或undefined。在ECMAScript3和非严格模式中,传入的null和undefined都会被全局对象替代。而其他原始值则会被相应的包装对象所替代。

8.bind()方法:bind()是在ECMAScript5中新增的方法,但在ECMAScript3中可以轻易模拟bind()。从名字可以看出,这个方法主要作用就是绑定至某个对象。当在函数f()上调用bind()方法并传入一个对象o作为参数,这个方法将返回一个新的函数。(以函数调用的方式)调用新的函数将会把原始的函数f()当做o的方法来调用。传入新函数的任何实参都将传入原始函数,比如:

function f(y){return this.x+y;}//这是个待绑定的函数

var o={x+1};//将要绑定的对象

var g=f.bind(o);//通过调用g(x)来调用o.f(x);

g(2)//=>3

在ECMAScri5中bind()方法不仅仅是将函数绑定至一个对象,它还附带一些其他应用:除了第一个实参之外,传入bind()的实参也会绑定至this。eg

varsum=function(x,y){

console.log(x+y);

}

//创建一个类似sum的新函数,但this的值绑定到null

//并且第一个参数绑定到1,这个新的函数期望只传入一个实参

varsucc=sum.bind(null,1);

succ(2);//=>3

在ECMAScript3中模拟实现标准的bind()方法

if(!Function.prototype.bind){

Function.prototype.bind=function(o){

var self=this,boundArgs=arguments;

return function(){

var args=[],i;

for(var i=1;i<boundArgs.length;i++){

args.push(boundArgs[i]);

}

for (var i = 0; i <arguments.length; i++) {

args.push(arguments[i]);

};

return self.apply(o,args);

};

};

};

我们注意到,bind()方法返回的函数是一个闭包。在这个闭包的外部函数中声明了self和boundArgs变量,而且调用这个变量在闭包里用到。尽管定义闭包的内部函数已经从外部函数中返回,而且调用这个闭包逻辑的时刻要在外部函数返回之后(在闭包中照样可以正确访问这两个变量)。

ECMAScript5定义的bind()方法也有一些特性是上述ECMASCript3代码无法模拟的。首先,真正的bind()方法返回一个函数对象,这个函数对象的length属性是绑定函数的形参个数减去绑定实参的个数(length的值不能小于零)。再者ECMAScript5的bind()方法可以顺带做构造函数。如果bind()返回的函数用作构造函数,将忽略传入bind()方法所返回的函数并不包含prototype属性(普通的函数固有的prototype属性是不能删除的),并且将这些绑定的函数用作构造函数时所创建的对象从原始的未绑定的构造函数中继承prototype。同样,在使用instanceof运算符时,绑定构造函数和未绑定构造函数并无两样。

时间: 2024-10-12 22:32:00

Javascript函数小结(二)的相关文章

javascript 学习小结 (二) by FungLeo

javascript 学习小结 (二) by FungLeo 前言 前面写过一个学习小结javascript 学习小结 JS装逼技巧(一) by FungLeo 那篇博文总结的东西还是比较多的. 但是JS有很多的内容,都是很有用的知识点,不可能一下子记住.因此,我的学习小结的会一直更新. 因为学习进度的不同,可能每篇博文的长短也不一样,有的学的东西多,就长点. 查询某个字符串在某个数组中的索引值 笨方法 我的基础比较差,所以很多东西是记不住的.因此,我在需要这样做的时候,我写了如下代码 var

Javascript函数小结(一)

函数是一个可以被调用和执行任意次的程序片段.JavaScript函数是参数化的:函数的定义会包括一个称为形参的标识符列表,这些参数在函数体中像局部变量一样工作.函数调用会为形参提供实参的值.函数使用它们实参的值来计算返回值.函数使用它们实参的值来计算返回值,成为该函数调用表达式的值.除了实参之外,每次调用还会拥有另一个值--本次调用的上下文--这就是this关键字的值. 如果函数挂载在一个对象上,作为对象的一个属性,就称它为对象的方法.当通过这个对象来调用函数时,该对象就是此次调用的上下文.也就

JavaScript 函数(二)

一.匿名函数 1.匿名函数 没有名字的函数即称为匿名函数. 2.使用方法 a.将匿名函数赋值给一个变量,这样就可以通过变量进行调用 b.匿名函数自调用 3.关于自执行函数(匿名函数自调用)的作用:防止全局变量污染. Demo: 1 //1 函数声明 - 命名函数 2 function fn() { 3 // 函数体 4 } 5 6 //2 函数表达式 -- 后半部分 匿名函数 7 var fn = function () { 8 // 函数体 9 } 10 11 // 3 自调用函数 -- 当函

JavaScript函数(二)

一.函数调用     1.函数调用:函数在定义好之后,不能自动执行,需要进行调用. 2.调用方式:在<script>标签内调用.在HTML文件中调用. <!DOCTYPE html> <html lang="en"> <head>     <meta charset="UTF-8">     <title>Title</title> </head> <body>

JavaScript权威设计--JavaScript函数(简要学习笔记十二)

1.作为命名空间的函数 有时候我们需要声明很多变量.这样的变量会污染全局变量并且可能与别人声明的变量产生冲突. 这时.解决办法是将代码放入一个函数中,然后调用这个函数.这样全局变量就变成了 局部变量. 如: function my(){ } my(); //别忘记调用 这段代码定义了一个单独的全局变量:名叫"my"的函数. 我们还可以这么写,定义一个匿名函数: (function(){ //这里第一个左括号是必须的,如果不写,JavaScript解析器会将 //function解析成函

Javascript常用方法函数收集(二)

Javascript常用方法函数收集(二) 31.判断是否Touch屏幕 function isTouchScreen(){ return (('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); } 32.判断是否打开视窗 function isViewportOpen() { return !!document.getElementById('wixMobileV

C#实现百度地图附近搜索&amp;调用JavaScript函数

前一篇文章"C#调用百度地图API入门&解决BMap未定义问题"讲述了如何通过C#调用百度API显示地图,并且如何解决BMap未定义的问题.这篇文章主要更加详细的介绍百度地图的一些功能,包括附近搜索.城市搜索.路线规划.添加覆盖物等等. 希望文章对你有所帮助!如果文章中有不足之处,还请海涵~ 百度官方文档:http://developer.baidu.com/map/jsmobile.htm 官方DEMO例:http://developer.baidu.com/map/jsde

基础JavaScript练习(二)总结

任务目的 学习与实践JavaScript的基本语法.语言特性 练习使用JavaScript实现简单的排序算法 任务描述 基于上一任务 限制输入的数字在10-100 队列元素数量最多限制为60个,当超过60个时,添加元素时alert出提示 队列展现方式变化如图,直接用高度表示数字大小 实现一个简单的排序功能,如冒泡排序(不限制具体算法),用可视化的方法表达出来,参考见下方参考资料 任务注意事项 实现简单功能的同时,请仔细学习JavaScript基本语法.事件.DOM相关的知识 请注意代码风格的整齐

04_内置函数(二)

内置函数(二) 1.1 callable() 功能:函数是否可调用 示例1: def f1(): pass f1() f2 = 123 f2() # 输出结果 TypeError: 'int' object is not callable 示例2: def f1(): pass # f1() f2 = 123 # f2() print(callable(f1)) print(callable(f2)) # 输出结果 True False 1.2 chr() 功能:数字转字母,返回对应的ASCII