对js中Function的浅见
它到底是什么
String Array 都是系统内置对象(已经定义好,可以直接使用)当然,这货也是一样,我们之前定义的函数,其实就是一个这货的实例。
在JS中,所有的对象都是由函数实现的,函数的数据类型是object。So,我们以前定义的函数也是一个对象。
几种写法
function fn1(a,b){
return a+b;
}
//前面表示参数,后面表示函数语句
var fn2 = new Function("a","b","return a+b");
// 匿名函数
var fn3=function(a,b){
return a+b;
}
console.log(fn1(1,2));
console.log(fn2(1,2));
console.log(fn3(1,2)); // 注意,一定要在声明函数的后面调用
另外,如果函数没有明确的返回值,或者调用了没有参数的return,那么它真正返回的值是undefined
function fn(){
//.....
}
function fn1(){
return;
}
console.log(fn()===undefined); // true
console.log(fn1()===undefined); // true
arguments
arguments只有在代码运行的时候才起作用,它是一个数组(准确的说是伪数组),保存函数的参数。
function fn(){
var sum=0;
for(var i=0;i<arguments.length;i++){
sum+=arguments[i];
}
return sum;
}
var sum = fn(1,2);
var sum2 = fn(1,2,3);
console.log(sum); //
console.log(sum2); //
function fn1(a,b,c,d){
console.log(arguments.length);
console.log(arguments[0]);
}
fn1(); // 0 、 undefined
fn1(1); // 1 、 1
fn1('a',2); // 2 、 a
fn1('李志',2,3); // 3 、 李志
fn1('李B',2,2,3,4,4); // 6 、 李B
Length
我们需要了解两个东东,形参与实参(不同的资料书籍可能叫法有所差异)
形参:函数定义的时候的参数 实参:调用函数的时候传递的参数
length指的是形参个数 arguments.length指的是实参个数
function fn(a, b) {
console.log(fn.length);
console.log(arguments.length);
}
fn(1, 2); // 2 2
fn(1); // 2 1
call apply
1,借用另一个对象的方法 2,替换this指向
Apply方法 调用函数,并用指定对象替换函数的this值,同时用指定数组替换函数的参数。
Call方法 调用一个对象的方法,用另一个对象替换当前对象。
//对象1
var obj1={
getAllStudentsNumbers:function(sum,sum1){
return sum+sum1}
}; //对象2
var obj2={
getDetail:function(){
return {name:'阿拉三',age:'18'}
}
};
console.log(obj1.getAllStudentsNumbers.call(obj2,10,200)); //
console.log(obj1.getAllStudentsNumbers.apply(obj2,[10,200])); //
Function.apply(obj,args)方法能接收两个参数
obj:这个对象将代替Function类里this对象
args:这个是数组,它将作为参数传给Function(args-->arguments)
我们通过如下方式将其转换成数组
/* slice : 截取数组,返回的还是数组,这里我们截取全部 */
var divs = document.getElementsByTagName("div")
var domNodes = Array.prototype.slice.call(divs);
还可以实现继承,在上篇文章中说过,这里不做赘述。
caller callee
caller属性 获取调用当前函数的函数。caller属性只有当函数正在执行时才被定义。
返回函数调用者,主要用于察看函数本身被哪个函数调用.
function fn() {
//判断某函数是否被调用
if (fn.caller) {
alert(fn.caller.toString());
} else {
alert("函数直接执行");
}
}
function fn1() {
fn();
}
fn1();
fn();
callee属性 返回正被执行的 Function 对象,即指定的Function 对象的正文。
如下是一个递归算法 - 计算 1+2+3+4+...+n
什么是递归? 可以这样理解,一个方法,自己调用自己,用上一次调用得出的结果作为这次的参数。
传统方式的缺点:
1、破坏了,零重复法则,当一旦函数名称更改,需要更改多处
2、fn是一个全局变量,fn内部一般使用局部变量,而这里是一个全局变量,这是一个潜在的全局变量污染
var fn=function(n){
return n>0 ? n+fn(n-1) : 0;
}
console.log('采用传统方式:'+fn(10));
优点:这样就让代码更加简练。又防止了全局变量的污染
var fn=(function(n){
return n>0 ? n+arguments.callee(n-1) : 0;
})(10);
console.log('采用callee方式: '+fn);
constructor prototype
constructor属性,就是用来构造对象实例的函数引用。
prototype属性,获取对象的原型。
每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。这意味着,我们可以把那些不变的属性和方法,直接定义在prototype对象上。
contructor,prototype属性是系统自动生成的。但本质上只是是函数对象的属性而已。
对象是一个函数,而函数对象含有contructor,prototype等属性,
那么实例化的过程就是拷贝构造函数属性的过程,所以每个实例自然就拥有了contructor,prototype这两个属性。
自定义对象:函数实现的--函数又是Function的一个实例,所以这个自定义对象含有Function对象的一切属性和方法
var product = function(){}
/*自动有一个 prototype属性 它是一个对象--- 原型对象*/
/* product.prototype也是对象,对象都是函数实现的,这货也包含Function对象的一切属性和方法,所以他也有。*/
product.prototype.buy=function(){}
product.prototype={}
bind
Bind方法,创建具有与原始函数相同的主体的绑定函数。 在绑定功能中,this对象解析为传入的对象。 该绑定函数具有指定的初始参数。
为了能在改变了上下文之后继续引用到this,大家通常选择使用self that _this 等方式先保存起来。这是完全可以的,现在有了bind:
var obj={
fn1:function(){
console.log(1);
},
fn2:function(){
console.log(2);
},
fn3:function(fn){
fn();
console.log(3);
},
fn4:function(){
// var that=this; // 还保存吗?
// this.fn3(function(){
// console.log(4);
// that.fn1();
// that.fn2();
// });
this.fn3(function(){
console.log(4);
this.fn1();
this.fn2();
}.bind(this)); // 咦,发生什么?
},
}
obj.fn4();
再看一眼:
var foo={
x:3,
}
var bar=function(){
console.log(this.x);
}
bar();
var boundFunc=bar.bind(foo);
boundFunc();
想到了什么?call? apply? 没错,看下面三者的区别:
fn1.hello.call(fn2,1,2,3);
fn1.hello.apply(fn2,[1,2,3]);
fn1.hello.bind(fn2)(1,2,3);
好消息是,IE8以下并不支持。肿么办?
没关系,大牛们写好了,我们来看一下
if (!Function.prototype.bind) {
Function.prototype.bind = function (oThis) {
if (typeof this !== "function") {
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
}
var aArgs = Array.prototype.slice.call(arguments, 1),
fToBind = this,
fNOP = function () {},
fBound = function () {
return fToBind.apply(this instanceof fNOP ? this : oThis || this ,
aArgs.concat(Array.prototype.slice.call(arguments)));
};
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
};
}
最后:
JS中,函数的使用是非常之灵活,比如闭包、立即函数、等等等等,以后有机会专门讨论。
对js中Function的浅见的更多相关文章
- js中function的与众不同
js中function的与众不同在于可以被调用
- js中function参数默认值
--在dreamweaver做网站时,函数定义是在一个*.js文件中,其中定义了一个func,有四个参数,function func(string1,url,flag,icon),然后在另一个asp中 ...
- 使用另一种方式实现js中Function的调用(call/apply/bind)
在JavaScript中函数的调用可以有多种方式,但更经典的莫过于call和apply.call跟apply都绑定在函数上,他们两个的第一个参数意义相同,传入一个对象,他作为函数的执行环境(实质上是为 ...
- js 中 (function($){...})(jQuery) 含义
js中定义函数常用写法是 function name(arg){ //arg则是匿名函数的参数. //... } 调用函数时的写法是: name(arg); ===================== ...
- prototype.js中Function.prototype.bind方法浅解
prototype.js中的Function.prototype.bind方法: Function.prototype.bind = function() { var __method = this; ...
- js中Function引用类型中一些常见且有用的方法和属性
Function类型 函数由于是Function类型的一个实例,所以函数名就是一个指向函数对象的指针,不会与某个函数死死的连接在一起,这也导致了js中没有真正的重载,但好处是,函数对象可以作为另一个函 ...
- js中(function(){})()的写法用处
直到今天我才明白的一个玩意!!! 来来来,首先嘛,JS中函数有两种命名方式 1.一种是声明式. 而声明式会导致函数提升,function会被解释器优先编译.即我们用声明式写函数,可以在任何区域声明,不 ...
- js中(function(){}()),(function(){})(),$(function(){});之间的区别
1. (function(){}())与(function(){})() 这两种写法,都是一种立即执行函数的写法,即IIFE (Immediately Invoked Function Express ...
- js中function函数
function:是具备某个功能的方法,方法本身没有意义,只有执行方法才有价值. function: 1 创建一个函数: 2 执行这个方法: 例: 创建 function 方法名(){ 存放某个功能的 ...
随机推荐
- 利用T4模板生成ASP.NET Core控制器的构造函数和参数
前言 在ASP.NET Core中引入了DI,并且通过构造函数注入参数,控制器中会大量使用DI注入各种的配置参数,如果配置注入的参数比较多,而且各个控制器需要的配置参数都基本一样的话,那么不断重复的复 ...
- Java泛型-类型擦除
一.概述 Java泛型在使用过程有诸多的问题,如不存在List<String>.class, List<Integer>不能赋值给List<Number>(不可协变 ...
- SQL Server2000导出数据时包含主键、字段默认值、描述等信息
时经常用SQL Server2000自带的导出数据向导将数据从一台数据库服务器导出到另一台数据库服务器: 结果数据导出了,但表的主键.字段默认值.描述等信息却未能导出,一直没想出什么方法,今天又尝试了 ...
- 基于吉日嘎底层架构的通用权限管理Web端UI更新:参考DTcms后台界面
经一周的研究学习,看了国内的H+.HUI等,国外的PaperDashboardPro.Make.Metronic BootStrap等,最终选定用一个轻量的,适合中国人的,来自DTcms的后台管理UI ...
- 透过IL看C#:switch语句(转)
透过IL看C# switch语句(上) 摘要: switch语句是 C#中常用的跳转语句,可以根据一个参数的不同取值执行不同的代码.本文介绍了当向 switch语句中传入不同类型的参数时,编译器为其生 ...
- jquery层级原则器(匹配后代元素div)
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- Win7 电脑设置临时网络,无法加入网络;internet禁止网络共享
1.电脑的本地连接中的共享,被管理员禁用.网上试了一些方法,都不可行.最后想到修改注册表.我找到了注册表中的shared选项.将0修改为1.则实现了本地连接的共享. 2.但是即便如此,由本地连接分享出 ...
- Spring IoC源码解决——工具篇Eclipse
题外话 对于Spring框架,平时都是点到为止,停留在会用的程度.一直以来都想深入学习下,刚好最近看到<Spring源码深度解析>,所以想随着书本深入学习一下. 如果用Maven 如果使用 ...
- netmiko初窥
paramiko 和 pexpect在笔记里被跳过 因为,他们都可以被netmiko所取代,不想在他们身上浪费太多时间 补一个地方就是,如果用paramiko遇到了connection莫名自己关闭的情 ...
- slid.es – 创建在线幻灯片和演示文稿的最佳途径
slid.es 提供了一种创建在线幻灯片和演示文稿的简单方法,让你通过几个简单的步骤制作效果精美的在线演示文稿.基于 HTML5 和 CSS3 实现,在现代浏览器中效果最佳. 您可能感兴趣的相关文章 ...