JS 学习笔记--8---Function类型
练习使用的浏览器IE11
JS 中Function类型实际上是一种对象,每一个函数实际上都是Function类型的一个实例,每一个函数都有一些默认的属性和方法。由于函数是对象,故函数名实际上也是一个指向函数对象的指针变量
1、声明一个函数
直接用关键字function来声明函数,JS是弱类型的语言,声明的时候参数个数不限,只是需要写参数名,不需要写参数的关键字var,不需要指定返回值以及类型,如果有返回值直接在函数后面一个return value 即可。
方法一:function func(num1,num2){return 1;}//num1,num2是参数名,返回值为1
方法二:利用变量来声明函数,var box=function(num1,num2){};相当于给window对象的自定义属性box注册方法
方法三:利用析构函数来声明,但是最好不要用这种方式来声明,因为这种方式浏览器会解析两次,效率不高,第一次是解析整个ECMAScript表达式,第二次是解析析构函数中传递的字符串列表,var box=new Function('num1','num2','return num1+num2');注意析构函数里面的参数以及语句是带有引号的。这种方式能够更好的理解 Function是一个对象的,函数名是一个指针的概念
2、调用函数
方法一中声明的函数直接写函数名就可以调用[fun(10,20)],
方法二和方法三声明的函数调用时用变量名后面加括号里面写上要传递的参数值[box(10,20)];
函数的返回值可以直接赋值给一个变量[var box=func(20,10);],也可以当做实参直接传递给另外的函数[alert(func(10,20));]
ECMAScript 中的函数名本身就是变量,所以函数也可以作为值来使用。也就是说,不仅可以像传递参数一样把一个函数传递给另一个函数, 而且可以将一个函数作为另一个函数的结果返回
//将一个函数作为结果返回 其实就相当于执行这个函数,然后把这个函数的返回值给返回function sum(num1,num2){return num1+num2;}function func(num1){return sum(num1,10);}alert(func(10));//20//其实函数名,也就是一个对象的变量,执行的是函数的地址,相当于一个指针
//将函数名当做一个参数传递给另外一个函数,function sumFunc(num1,num2){return num1+num2;}function func(sum,num1){return sum(num1,10);}alert(func(sumFunc,10));//20
JS 中没有函数重载的说法,函数调用的时候,会以就近原则来调用
JS 中调用函数的时候允许调用者和被调用这的参数个数不一样,也不会报错,但是如果参数个数不够的话,在执行时因为有的参数没有赋值可能会报错,参数时从前向后对应传递接收的
3、函数的内部属性 arguments
arguments 是一个类数组,用来保存函数传递过来的参数,数组类型
在声明函数的时候,有的时候我们并不知道调用者到底要传递多少个参数过来,比如说,求一串数的累加和,如果调用者不是用数组传递过来而是用直接传递给函数的方式传递[func(10,20...)],那么在声明函数实体的时候就不知道要声明多少个参数,这时可以不写参数名,在函数内部用arguments来代替,arguments是一个类数组,保存的是拥有这个对象的函数的参数的值,用索引的方法既可以获取对应的参数的值,使用如下:
function func(){var res=0;for(var i=0;i<arguments.length;i++){res+=arguments[i]+" | ";}return res;}alert(func(20,30,40));
arguments 中还有一个很重要的属性就是callee,是一个指针变量,指向的是拥有这个arguments类数组的函数,其实也就是arguments所在的函数本身,在递归的时候最好用这个属性,因为如果函数名改变了,也不需要改变内部的实现,arguments.callee()始终代表的是这个函数本身
//用arguments.callee的好处是,当函数名改变了以后,不需要改动递归出的函数,function box(num){if(num<=1){return 1;}else{return num*arguments.callee(num-1);//arguments.callee代表的是函数的本身,故和上面是同样的效果}}alert(box(3));//6
4、函数的内部属性 this
this 这个属性代表的是它所在的对象本身,和C#中this代表实体对象本身是一样的,this 引用的是函数以执行操作的对象,或者说函数调用语句所处的那个作用域
window是JS中最大的一个对象,在window对象中声明一个变量其实就是给window这个对象声明一个属性,var box=1;相当于 window.box=1;也就等价于this.box=1;
当在全局作用域中调用函数时,this 对象引用的就是 window。
在显示的声明一个对象box,这个box中使用的this就代表的是box本身,this.color就是返回的box中属性color的值,而不是window对象中color的值
// this 代表的是坐在的对象本身,下面在对象box中的this,就代表对象boxvar color='红色'; // window对象的属性,var box={color:'蓝色',run:function(){alert(this.color);//蓝色return this.color;}}alert(window.color);//红色alert(this.color); //红色 此处this代表的是window对象,故this.color是代表的window的属性alert(box.run()); //蓝色window.co='hh'; //和上面的color是等价的,都属于window对象的属性alert(this.co);
5、函数的属性 length
函数的属性length代表的是函数希望接收的参数的个数,是由声明函数时参数列表中的个数决定的
6、函数的属性 prototype
prototype 是保存所有实例方法的真正所在,也就是原型。
prototype 下面有两个方法 apply(),call(),这两个方法都是函数非继承而来的方法, 是每一个函数都具有的方法。这两个方法的用途都是在特定的作用域中调用函数,也就是说调用特定的对象下面调用函数,(当然这个对象不一定已经声明有这个方法),实际上也就是等价于设置函数内部this对象的值,有点类似于C#的反射中调用对象的方法。
func.apply():这个方法有两个参数,第一个是要执行这个方法的作用域,也就是传递一个对象过去,第二个参数是一个数组,这个数组中是存放的调用的函数func的实参,也就是要传递给func的值,当然第二个参数可以省略。func.apply(this, [num1, num2]);。如果是在一个函数中调用可以用arguments把这个函数的参数传递过去,前提是这个类数组中有参数。但是最好是保证这个类数组中存放的是你想要传递给func函数的实参的值。虽然个数不匹配也不会出错,但是业务上可能不对
func.call():这个方法和上面的apply()方法是一样的,不同的是参数,第一个同样是作用域,是一样的,其余的参数是直接传递给函数的,而不是传递一个数组过去。就是说传递的参数顺序和方式是按照正常调用函数的形式和方法。func.call(this, num1, num2);
这两个方法最主要的功能是是能够扩展函数赖以运行的作用域,也就是改变函数运行所在的作用域
使用这apply()和call()这两个方法来扩充作用域最大的好处是对象不需要与方法发生任何的耦合关系,也就是上面说的对象中可能不存在这个方法,但只要存在这个对象就OK。【耦合:关联的意思,修改和维护会发生连锁反应】。也就是说 box 对象和sayColor()方法之间不会有多余的关联操作,比如 box.sayColor = sayColor;[ box对象中无需显示写上这条语句,也可以通过sayColor.call(box,'red')或者apply来调用方法sayColor,并且调用时sayColor方法的作用域是在对象box内部 ].
//call()和apply()方法最主要的是用于扩展函数依赖的作用域var color='red';
var box={color:'green'
}function sayColor(){return this.color;
}alert(sayColor()); //red 对象是window
alert(sayColor.call(this)); //red 对象是window
alert(sayColor.apply(this)); //red 对象是window
alert(sayColor.call(window)); //red 对象是window
alert(sayColor.apply(window)); //red 对象是window
alert(sayColor.call(box)); //green 对象是box
alert(sayColor.apply(box)); //green 对象是box
练习的代码:以IE10为主
1 /* 函数的声明 2 3 //声明一个函数,没有参数和返回值 4 function func(){ 5 alert('diao yong di shi hou zhi xin'); 6 } 7 func(); 8 9 //声明一个函数,带有两个参数,由于JS是弱类型的语言,故函数的参数时不需要使用var的 10 function func(num1,num2){ 11 alert(num1+num2); 12 } 13 func(10,20); 14 15 //声明一个函数,带有两个参数和返回值,JS中返回值直接用return即可,函数名前不需要标注带有返回值 16 function func(num1,num2){ 17 return num1+num2; 18 } 19 alert(func(10,20));//30 20 21 //可以把函数的返回值直接赋值给一个变量,然后直接操作变量 22 function func(num1,num2){ 23 return num1+num2; 24 } 25 var a=func(10,20); 26 alert(a); //11 27 28 //return还有一个功能就是,结束函数的执行 29 function func(num1,num2){ 30 if(num1>10){ 31 return 11; 32 } 33 return num1+num2; 34 } 35 alert(func(13,20)); //11 36 37 // JS 调用的时候传递的参数个数和函数原型中参数个数可以不一样 38 function func(num1,num2){ 39 return num1+num2; 40 } 41 42 alert(func(20,'ahc',9)); 43 44 //ECMAScript 函数不介意传递进来多少参数,也不会因为参数不统一而错误。实际上, 45 函数体内可以通过 arguments 对象来接收传递进来的参数,arguments 可以用数组来取值 46 function func(){ 47 var res=0; 48 for(var i=0;i<arguments.length;i++){ 49 res+=arguments[i]+" | "; 50 } 51 return res; 52 } 53 54 alert(func(20,30,40)); 55 56 // JS 中没有函数重载的说法,函数和变量等的调用都是就近原则 57 function func(num1,num2){ 58 return num1+num2; 59 } 60 function func(num1){ 61 return num1; 62 } 63 alert(20,30);//20 执行的第二个函数,就近原则 64 65 //将一个函数的返回结果值作为另外一个函数的参数进行传递 66 function sum(num1,num2){ 67 return num1+num2; 68 } 69 70 function func(num1){ 71 return num1+10; 72 } 73 alert(sum(func(10),10));//30 74 75 //用变量初始化的方式声明一个函数,然后用变量名加参数列表来调用这个函数 76 //这种声明方法,就是给变量名注册一个事件的形式 77 var box=function(num1,num2){ 78 return num1+num2; 79 } 80 alert(box(10,10));//20 81 82 //使用析构函数来声明一个函数,但是这种方法效率低,因为会解析两次 83 //第一次解析整个表达式(ECMAScript常规代码),第二次就是解析传入构造函数中的字符串 84 //用这种方式能够更好的理解函数是对象,函数名是一个指针的概念 85 var box=new Function('num1','num2','return num1+num2'); 86 alert(box(10,10));20 87 88 */ 89 90 /* 91 //将一个函数作为结果返回 其实就相当于执行这个函数,然后把这个函数的返回值给返回 92 function sum(num1,num2){ 93 return num1+num2; 94 } 95 function func(num1){ 96 return sum(num1,10); 97 } 98 alert(func(10));//20 99 100 //Function类型其实也是一个对象,既然是对象,那也就具有和其他对象一样的属性方法等, 101 //其实函数名,也就是一个对象的变量,执行的是函数的地址,相当于一个指针 102 //将函数名当做一个参数传递给另外一个函数, 103 function sumFunc(num1,num2){ 104 return num1+num2; 105 } 106 function func(sum,num1){ 107 return sum(num1,10); 108 } 109 alert(func(sumFunc,10));//20 110 111 */ 112 113 /* 函数的内部属性 arguments 和 this 114 //函数的递归 115 function box(num){ 116 if(num<=1){ 117 return 1; 118 }else{ 119 return num*box(num-1);//自己调用自己 120 } 121 } 122 alert(box(3));//6 123 124 //arguments 是一个类数组,用来保存函数传递过来的参数,数组类型 125 //arguments.callee 是一arguments的一个属性,是一个指针变量, 126 //指向的是拥有这个argumens属性的函数,也就是说代表了他所在的这个函数本身 127 //用arguments.callee的好处是,当函数名改变了以后,不需要改动递归出的函数, 128 function box(num){ 129 if(num<=1){ 130 return 1; 131 }else{ 132 return num*arguments.callee(num-1); 133 //arguments.callee代表的是函数的本身,故和上面是同样的效果 134 } 135 } 136 alert(box(3));//6 137 138 // this 对象代表的是对象的本身 139 // 和 C# 中的this差不多,C# 中的this代表的也是实例化的对象的本身 140 //默认情况下 this 带表的是window对象,window是JS中最大的一个对象 141 //从下面可以看出 在window对象下 this就等于window 142 alert(window); //object Window 143 alert(typeof window); //object 144 alert(this); //object Window 145 alert(typeof this); //onject 146 147 var color='hong se'; // color 是window的一个属性 148 alert(window.color); //hong se 输出window的属性 149 alert(this.color); //hong se 和上面结果相等,说明this在此处代表的是window对象的本身 150 151 // this 代表的是坐在的对象本身,下面在对象box中的this,就代表对象box 152 var color='红色'; // window对象的属性, 153 154 var box={ 155 color:'蓝色', 156 run:function(){ 157 alert(this.color);//蓝色 158 return this.color; 159 } 160 } 161 alert(window.color);//红色 162 alert(this.color); //红色 此处this代表的是window对象,故this.color是代表的window的属性 163 alert(box.run()); //蓝色 164 165 window.co='hh'; //和上面的color是等价的,都属于window对象的属性 166 alert(this.co); 167 168 // 下面是通过给对象添加方法来改变this的作用域 169 window.color='红色'; //等价于 var color='红色' 170 171 var box={ 172 color:'蓝色' 173 }; 174 175 function sayColor(){ 176 alert(this.color); 177 } 178 179 sayColor(); // 红色 180 box.sayColor=sayColor; //给对象添加一个方法, 181 //上面这句话改变了 sayColor 的作用域在box对象里面,故这个方法里面的this也就是指的box对象 182 box.sayColor(); // 蓝色 183 184 */ 185 186 /* 函数的属性和方法 length,prototype[原型,标准] 187 188 // 函数中的length属性返回的是函数的参数的个数 189 function box(nm1,num2){}; 190 alert(box.length); // 2 191 function func(num1,num2,num3,num4){}; 192 alert(func.length); // 4 193 // prototype 属性是保存实例方法的真正所在的位置,也就是保存的原型 194 //包含两个非继承而来的方法 apply()和call()方法,都是用在特定的作用域中调用, 195 //相当于改变函数的this,也就是说改变函数所处的对象,有点像C#中的反射调用对象方法 196 197 // box.apply()方法,两个参数,第一个参数是要操作的对象,第二个参数是方法的参数数组 198 function sum(num1,num2){ 199 return num1+num2; 200 } 201 202 function saySum1(num1,num2){ 203 //第一个参数时代表的是要调用的是哪一个对象的sum方法,后面是这个方法的参数列表,注意传递的是一个数组 204 return sum.apply(this,[num1,num2]);//this相当于window 205 } 206 function saySum2(num1,num2){ 207 return sum.apply(this,arguments); 208 //arguments 代表的是当前函数[saySum2]的参数列表,是一个类函数,直接传递给函数sum 209 } 210 alert(saySum1(10,20)); //30 211 alert(saySum2(10,20)); //30 212 213 //第一个参数的不同,函数的作用域是不一样的 214 function sum(num1,num2){ 215 return num1+num2; 216 } 217 218 function saySum1(num1,num2){ 219 return sum.apply(this,arguments);//是在window对象中执行的 220 } 221 function saySum2(num1,num2){ 222 return sum.apply(box,arguments);//是执行在box对象中的方法 223 } 224 var box ={ 225 num1:'acd', 226 num2:'ddd', 227 } 228 alert(saySum1(10,20)); //30 229 alert(saySum2(10,10)); //20 230 231 //方法 call()和上面的apply()方法是一样的,仅仅在于接收参数的方式不同 232 //call()第一个参数同样是传递作用域对象,其余的参数是直接传给函数的,而不是传递一个数组 233 234 function sum(num1,num2){ 235 return num1+num2; 236 } 237 238 function saySum1(num1,num2){ 239 return sum.call(this,num1,num2) 240 } 241 242 function saySum2(num1,num2){ 243 return sum.call(box,num1,num2); 244 } 245 var box={}; 246 247 alert(saySum1(10,20));//30 248 alert(saySum2(20,20));//40 249 250 //call()和apply()方法最主要的是用于扩展函数依赖的作用域 251 252 var color='red'; 253 var box={ 254 color:'green' 255 } 256 257 function sayColor(){ 258 return this.color; 259 } 260 261 alert(sayColor()); //red 对象是window 262 alert(sayColor.call(this)); //red 对象是window 263 alert(sayColor.apply(this)); //red 对象是window 264 alert(sayColor.call(window)); //red 对象是window 265 alert(sayColor.apply(window)); //red 对象是window 266 alert(sayColor.call(box)); //green 对象是box 267 alert(sayColor.apply(box)); //green 对象是box 268 */
View Code
转载于:https://www.cnblogs.com/qigang/p/3511710.html
JS 学习笔记--8---Function类型相关推荐
- WebGL three.js学习笔记 6种类型的纹理介绍及应用
WebGL three.js学习笔记 6种类型的纹理介绍及应用 本文所使用到的demo演示: 高光贴图Demo演示 反光效果Demo演示(因为是加载的模型,所以速度会慢) (一)普通纹理 计算机图形学 ...
- JS学习笔记(五)函数类型、箭头函数、arguments参数、标签函数
JS学习笔记(五) 本系列更多文章,可以查看专栏 JS学习笔记 文章目录 JS学习笔记(五) 一.函数 1. 函数定义 2. 方法( 对象 + 函数 ) 二.函数参数及返回值 1. 传递原始类型参数 ...
- 基于jquery的插件turn.js学习笔记
基于jquery的插件turn.js学习笔记 简介 turn.js是一个可以实现3d书籍展示效果的jq插件,使用html5和css3来执行效果.可以很好的适应于ios和安卓等触摸设备. How it ...
- Vue.js学习笔记 2022 04 17
Vue.js学习笔记 1 Vue.js基础 Vue.js介绍 vuejs 渐进式 JavaScript 框架 Vue.js 如何应用 1 在普通html项目中,引入VUE.JS Hb 的项目 生成的 ...
- Wow.js学习笔记
Wow.js学习笔记 前期准备 注意:通过引入cdn的树懒,注意版本问题(小白我就是因为失败就去乖乖下载wow.js本地文件) 1.wow.js 因依赖于animate.css,首先在头部引用anim ...
- JS学习笔记(九)深拷贝浅拷贝【Array、Object为例】
JS学习笔记(九) 本系列更多文章,可以查看专栏 JS学习笔记 文章目录 JS学习笔记(九) 一.赋值&复制 二.浅拷贝(shallow copy) 1. 什么是浅拷贝 2. 数组的浅拷贝 ( ...
- 千锋Node.js学习笔记
千锋Node.js学习笔记 文章目录 千锋Node.js学习笔记 写在前面 1. 认识Node.js 2. NVM 3. NPM 4. NRM 5. NPX 6. 模块/包与CommonJS 7. 常 ...
- three.js学习笔记(十八)——调整材质
介绍 到现在为止,我们都在创建新的着色器材质,但是如果我们想要修改一个Three.js内置的材质呢?或许我们对MeshStandardMaterial的处理结果感到满意,但是希望往里边添加顶点动画. ...
- ArcGIS JS 学习笔记4 实现地图联动
原文:ArcGIS JS 学习笔记4 实现地图联动 1.开篇 守望屁股实在太好玩了,所以最近有点懒,这次就先写个简单的来凑一下数.这次我的模仿目标是天地图的地图联动. 天地的地图联动不仅地图有联动,而 ...
- backbone.js学习笔记
backbone.js学习笔记 之前只接触过jQuery,看来Backbone是除了jQuery的第二大JS框架... backbone到底是个啥? 其实刚开始我也不知道=_=,我是这周二才听说居然还 ...
最新文章
- PayPal Agility with Stability On OpenStack
- Dreamoon Likes Coloring CodeForces - 1330C(贪心+思维)
- 5.1 入门整合案例(SpringBoot+Spring-data-elasticsearch) ---- good
- linux字符驱动之点亮LED
- Lydsy2017年4月月赛 抵制克苏恩
- 腾讯微信支付支持全量商家小程序场景开通云闪付功能
- 中消协:要选择优质电子显示产品 OLED屏整体上略胜一筹
- JavaScript中一些常用的方法整理
- 20190909 SpringBoot集成Swagger
- rqnoj71 拔河比赛
- FPGA实现sobel边缘检测并Modelsim仿真,与MATLAB实现效果对比
- matlab 保存成csv,怎么将matlab中数据保存为csv或xls格式
- 基于XC7K325T光纤传输的PCIE光纤卡、2路光纤的资料
- 爬虫学习——初步了解爬虫
- block与“阻塞(pend)”与“挂起(suspend)”的区别?
- /var/log/journal日志清理
- 前端eslint+prettier+lint-staged配置
- 关于错误提示:could not find a part of path “X:\”的解决办法
- 罗技k380键盘-数字键上的字符对不上怎么办?
- Chrome谷歌浏览器,清除css或js文件缓存的方法
热门文章
- linux git hook,前端通过githook一键自动部署项目
- matlab详细手册,matlab详细手册
- 单总线和i2c总线结合实现数字温度计的设计c语言程序,1《单片机原理应用》课程设计指导书2010-6-8.doc...
- mysql56数据库的创建_如何在Mysql下用命令创建数据库用户方法
- wordpress创建_如何创建WordPress儿童主题
- Python strftime()
- javascript进阶课程--第三章--匿名函数和闭包
- 婚纱摄影五大标杆品牌告诉你,客资转化居然可以这么玩?
- 问题3:点击应用icon,会卡几秒后才进入到启动界面
- RAC-DG 安装总结