文档章节

前端基础(三):函数

老司机带你撸代码
 老司机带你撸代码
发布于 06/19 21:08
字数 1506
阅读 14
收藏 0
点赞 0
评论 0

字数:1685

阅读时间:5分钟

函数定义

在最新的ES规范中,声明函数有4中方法:

-函数声明

-函数表达式

-构造函数Function

-生成器函数

1.函数声明

语法:

function name([param[, param2 [...]]]){

	[statements]

}

name:函数名称

param:需要传递给函数的参数的名称。有最大参数数量限制,不同引擎限制不同。

statements:包含函数体的语句

函数的最基本用法,注意会有声明提升机制。

2.函数表达式

语法:

var name = function(param [,param [...]]){

        [statements]

}

或

let name = function(param [,param [...]]){

        [statements]

}

用法同函数声明,使用let时,是块级作用域。

如下代码,我们就能看出函数声明与函数表达式的差异:

testFun(); //testFun
function testFun () {
    console.log('testFun');
}

console.log(typeof testFun1); //undefined
var testFun1 = function () {
    console.log('testFun1');
};

以第一个是函数申明提升,所以我们可以在声明之前使用函数。第二个是var变量声明提升,在声明之前它的值是undefined,所以无法直接使用。

3.Funcion构造函数

语法:

new Function([arg1 [ ,arg2 [,arg3 [...]]] ,] functionBody);

参数:

arg1, arg2, ... argN

​ 函数使用的参数列表

functionBody

​ 一个包含函数定义的语句字符串

JS中,所有的函数都是Function构造函数的实例。Object内置对象实质也是一个函数,所以,Object也是继承自Function的。而且,Function本身也是一个函数,因此,它自己也继承自己。

Function.prototype === Function.__proto__;	//true

使用这种方法创建函数有以下三点缺点:

1.使用Function创建的函数只有在运行到 new Function()语句时,才会解析函数。上面两种方式创建的函数,是与JS代码一起解析的。所以,使用Function函数创建的函数效率更低。

2.函数都是在全局作用域中创建的,无法使用创建时的上下文作用域。

let msg = 'testFun3 global';
function testFun3 () {
    let msg = 'testFun3 inner';
    let testFun4 = new Function('console.log(msg);');
    testFun4();
}
testFun3(); //testFun3 global

3.代码书写在字符串中,不利于维护。

所以,尽量不要使用该方式定义函数。

4.function*

语法:

function* name([param[, param[, ... param]]]) { statements }

参数同 1

定义一个生成器函数。

基础用法:

function * generator (i) {
    yield i;
    yield i + 1;
    let y = yield i + 2;
    yield y;
}
let gen1 = generator(0);
console.log(gen1.next()); //{value: 0, done: false}
console.log(gen1.next()); //{value: 1, done: false}
console.log(gen1.next()); //{value: 2, done: false}
console.log(gen1.next(100)); //{value: 100, done: false}
console.log(gen1.next()); //{value: undefined, done: true}

调用next函数时,传入的值是赋予上一个yield的返回值。

有浏览器兼容性问题,IE所有版本都不支持该用法。

函数调用

###直接调用

语法:

funName([arg1 [,arg2 , [arg3 [...]]]]);

最常用方式,不予赘述。

apply

语法:

func.apply(thisArg [ ,argsArray])

参数:

thisArg

​ 可选参数,将参数作为函数执行的this值使用。

​ 如果处于非严格模式下,传值为null或者undefined时,就将全局对象绑定到函数的this上。如果传值为原始值(数字、字符串、布尔),则会将this指向原始值的包装对象(Number、String、Boolean)

argsArray

​ 可选参数,传入一个数组或者类数组的值,作为函数的参数列表。

一般情况下,我们直接调用函数即可,在一些特殊的应用场景下,我们才会需要用到apply函数。例:

let Obj = {
    name: 'obj',
    print: function () {
        console.log(this.name);
    }
};
function success (callback) {
    this.name = 'success obj';
    callback(); 	//success obj
    callback.apply(Obj); 	//obj
}
success(Obj.print);

如上,如果我们将函数作为参数传递时,为了保证this的指向,就可能需要使用apply方法。

call

语法:

fun.call(thisArg, arg1, arg2, ...)

用法同apply,只是参数数组改为了参数列表。

作为构造函数调用

语法:

new constructor[([args])]

参数:

constructor

​ 一个类或者函数。

args

​ 类或者函数的参数列表,new constructor 等同于 new constructor().

当使用new Foo(...)来调用一个函数时,其实发生了如下三件事。

①创建一个继承自Foo.prototype的新对象。

②调用Foo函数,并将新建的对象作为this绑定到当前函数的执行上下文中。

③如果函数有返回值,就返回该值;否则,直接返回第一步创建的对象。

举个栗子:

function Foo (name) {
    this.name = name;
}

var foo1 = new Foo('Tom');
var foo2 = Object.create(Foo.prototype);
Foo.call(foo2, 'Tom');
console.log(foo1 instanceof Foo); //true
console.log(foo2 instanceof Foo); //true

对象方法调用

语法:

obj.foo([args])

var pFoo = obj.foo;
pFoo([args]);

这种方式就是对象的属性值为函数的时候,我们调用函数的情况。

用法基本和直接调用一致,其实通过第一种方式调用,实质就是在全局对象上声明了一个函数变量,然后通过全局对象来调用这个函数,所以他们的表象和使用方法类似。

但是这里,我们需要注意一点,就是我们通过对象属性调用和声明一个变量来获取函数值而后调用有使用上的区别。

举个栗子:

var obj = {
    foo: function (name) {
        this.name = name;
        console.log(this);
    }
};

obj.foo('Tom'); //obj
var pFoo = obj.foo;
pFoo(); //window

如上栗子,直接调用,this指向的是 obj 对象,但如果通过变量赋值后,this指向的是当前函数调用语句的上下文环境,这里我是浏览器环境,并且在顶层作用域中执行,所以this指向的是window对象。

总结

函数定义有函数声明、函数表达式、Function构造函数、function*四种方式。前面两种最常用,但是要注意this的指向问题(由于函数声明的作用域问题,我建议尽量使用函数表达式)。Function构造函数官方推荐不要使用,funtion*生成器函数是ES2015出现的新特性,使用时需要注意兼容性。

函数调用有函数直接调用、apply、call、作为构造函数调用、对象方法调用。他们各有针对的使用场景,需要注意的是对象方法调用中的this指向问题。

欢迎关注我的微信公众号:

© 著作权归作者所有

共有 人打赏支持
老司机带你撸代码
粉丝 45
博文 22
码字总数 36413
作品 0
武汉
高级程序员
推荐|前端开发者需要牢靠掌握的几项基本技能

开发者通常面对的是一个技术不断更新发展的生态,我们迫不及待的汲取新技能,将其在互联网上进行运用,当然这没有什么不好,只是有时候我们也该放慢自己的步伐,回首看看那些年一直没有改变的...

inw3cschool
2017/05/08
0
0
零基础如何系统地学习前端开发?

原文出处:@张帅在地上 网站开发开发大致分为前端和后端,前端主要负责实现视觉和交互效果,以及与服务器通信,完成业务逻辑。其核心价值在于对用户体验的追求。可以按如下思路学习系统学习:...

@张帅在地上
2015/11/27
0
0
适合初级前端程序员:闭包是什么?

是什么? 当一个嵌套的内部函数引用了外部函数的变量或者函数时,外部函数在执行时就产生了闭包 典型的闭包 将另一个函数作为另一个函数的返回值 将函数作为实参传递给另一个函数调用 闭包的...

IT智云编程
07/12
0
0
前端的知识体系如上,可以按以下思路进行系统的学习

  前端的知识体系如上,可以按以下思路进行系统的学习,以下是峰峰特别分享:   【基础知识】   1. html + css 这部分可以在w3cschool 在线教程上学习(网址:www.w3cschool.cn),边学边...

尹华峰博客
2017/06/14
0
0
Meteor——不一般的全栈开发平台!

一、全栈开发平台 - 不仅仅是前端 Meteor和那些名声如雷贯耳的前端框架,比如Angular, React等都不一样,它是一个 采用单一开发语言的全栈开发的平台:开发者可以使用JavaScript同时 进行前端...

笔阁
2015/09/15
2.2K
0
Meteor,单一开发语言的全栈开发的平台!

一、全栈开发平台 - 不仅仅是前端 Meteor和那些名声如雷贯耳的前端框架,比如Angular, React等都不一样,它是一个采用单一开发语言的全栈开发的平台:开发者可以使用JavaScript同时 进行前端...

笔阁
2015/10/09
1K
1
2018年web前端学习路线图

前端的的技术一直在变化,更新和变革,现在基本是三驾(vue,angualr,react)主导整个前端框架,但是无论对于新人或者有经验的程序员,这些知识在必须掌握 前端架构 上图罗列了整个前端的一些技...

技术金三胖
01/02
0
0
Javascript一些小细节

1.判断class存在 1 $(obj).hasClass('BTCheck_ON')2 $obj.attr('class')=="BTCheck_ON" 有时我们判断样式存在会写成第二种形式,但是这种写法是有问题的。如果那个DOM元素设置是class="BTCh...

技术小美
2017/11/12
0
0
前端面试题中常见的会犯错的题目-作用域链剖析

网上经常可以查到很多的前端面试题,很多都是很基础的东西,但是仍然不免有很多的童鞋会出错,不是因为他们技术不够啊什么的,很多时候就最基础的东西忘记了而已; 我们来看这样的一段简单的...

梅气灶
2015/10/13
100
2
jQuery

前端基础进阶:全方位详细图解面向对象、构造函数、原型与原型链 这是一篇非常适合新手理解关于面向对象一切的文章,解答了为什么我们会使用构造函数与原型,构造函数与原型的本质以及 new ...

掘金官方
01/08
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

第三章 spring-bean之beanFactory系列(1)

前言 spring的基本问题,每次面试基本会问题。比如 - spring是什么回答是ioc,aop,第三个就是beanfactory。 - spring使用什么模式,100%的人回答是工厂模式。 - 这面的问题大家都知道。关于...

鸟菜啊
13分钟前
0
0
箭头函数

var foo = v => v;// 等同于var foo = function (v) {return v;} 如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分 var f = () => 5;// 等同于var f = functio...

litCabbage
14分钟前
0
0
软件入门的知识之程序设计语言Java和C#的简单介绍和对比[图]

软件入门的知识之程序设计语言Java和C#的简单介绍和对比[图]: 前言: 要做软件就必然会涉及到程序设计语言,它是什么?有哪些特点?又有哪几部分组成的呢?在这里我们为大家做了一个总结,希...

原创小博客
15分钟前
0
0
重写视频播放进度条

需要注意的地方,基于html vedio 标准使用期去了解一下 1.想去掉视频默认的播放条,去掉controls属性。 2.需要预加载视频加上preload="auto"属性。 1.js代码 $(function(){ init(); }); var ...

轻量级赤影
23分钟前
0
0
saltstack管理任务计划-添加&删除

1.服务端配置 >>编辑 top.sls 文件 # vim /srv/salt/top.sls //修改为如下 base: '192.168.*.*': - crontest >>编辑crontest.sls文件添加计划任务 cron-test: cron.present: - name: /bin/to......

硅谷课堂
24分钟前
0
0
sql中多表查询及其左连字段

SELECT s.*,t.teach_name FROM `stu` s, `teacher` t WHERE s.teacher_id = t.row_id AND s.teacher_id = 1 s.* s表中 全部字段 t.teach_name t表中teach_name 字段 SELECT s.*,t.teach_nam......

森火
26分钟前
0
0
ES9-mapping参数

1.概述 ElasticSearch提供了丰富的参数对文档字段进行定义,比如字段的分词器、字段权重、日期格式、检索模型等等。可以查看官网每个参数的定义及使用:https://www.elastic.co/guide/en/ela...

贾峰uk
29分钟前
1
0
Java泛型学习

一、泛型的概念 List list = new ArrayList(); list.add("corn"); String name = (String) list.get(0); 1、这里将一个对象放入集合中,集合不会记住次对象的类型,当再次从集合中取出此对象...

cjxcloud
31分钟前
0
0
android屏幕适配

android屏幕适配 今日头条的适配方式:https://mp.weixin.qq.com/s/d9QCoBP6kV9VSWvVldVVwA 采用的是鸿阳的适配方式,项目依赖: compile 'com.zhy:autolayout:1.4.5' 使用步骤: 在manif...

android-key
35分钟前
0
0
istio 0.8 安装步骤

============================ istio 0.8 安装步骤--------------------------------------- istio 0.8 安装步骤 1.安装k8s环境 参考:http://sealyun.com/pro/products/ master,salve两台机......

xiaomin0322
38分钟前
12
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部