摘要:之前的函数声明及表达式函数的声明函数表达式也可以此时的只是这个匿名函数的名字,和变量没有关系构造函数这种方法会运行两次代码先实例后执行函数体数的默认值如果没有传入参数就使用默认值,利用的短路特性传入的参数为值会忽略判断是否传参,如果没
ES5之前的函数声明及表达式
1,函数的声明
</>复制代码
function fn(){
dosomething;
};
2,函数表达式
var fn = function(){}
//也可以var fn = function newFn(){},此时的newFn只是这个匿名函数的名字,和变量没有关系;
3,构造函数
</>复制代码
var fn = new Function("num1","num2","return num1 ,num2") //这种方法会运行两次代码
//先实例后执行函数体
ES5数的默认值
</>复制代码
function fn(arg1,arg2){
arg2 = arg2 || "the value"; //如果没有传入参数就使用默认值,利用||的短路特性
return arg1+arg2;
};
fn("hello") ->hello the value;
fn("hello","world") ->hello world;
fn("obama","")->obama the value //传入的参数为falsey值会忽略
typeof arg2 === "undefined" //判断是否传参,如果没有实参的话,就是undefined;
arg2=(typeof arg2 !=="undefined")?arg2:"the value";//判断是否有传入值
arguments.length ===1 //判断传递的参数个数
ES6的参数默认赋值
</>复制代码
function fn(arg1,arg2 = "value"){
let arg2 = 34; //此处的arg2 默认是已经声明,所以内部使用let const会语法报错!
console.log(arg1,arg2)
}
//内部的arguments对象也默认和严格模式一样的行为,不在动态的反应变化;默认值不计入arguments对象
//函数的参数,也可以是其他值,默认参数只有在调用的时候才会求值,因此可以用第一个参数作为默认的值
function fn(a , b =a){};
//参数的作用域和ES6之前的一样,和其他的参数都是同一作用域,如果参数的值是一个变量,那么这个参数的作用域先是局部(确认是否也是形参)后是全局;
let a = 34;
function fn(b = a){ //尤其注意,参数b赋值的是变量a,那么就默认变量a已经声明,此时的a,如果不是参数,就是全局的变量,如果是参数,就会报错,重复赋值,使用let和const要注意语法错误
let a= 11;
console.log(b);
}
fn() ->34 //当参数b赋值变量a的时候,a是全局注册的,因此,fn()是34,如果没有let a = 34;就会报错,
fn(22) ->22 //此时参数的作用域是局部
let a = 23;
function (a,b=a){ //参数b的值是a,相当于再次给a赋值,由于参数是函数内部变量,所以和 let a = 12冲突;会报错
let a = 12;
console.log(b);
}
function fn(arg1,arg2){
console.log(arg1 === arguments[0]); //true
console.log(arg2 === arguments[1]); //true
arg1 = newarg1;
arg2 = newarg2;
console.log(newarg1 === arguments[0]); //true
console.log(new arg2 === arguments[1]); //true
}
rest参数(...rest)不定参数;只能放在形参的最后面,否则会报错,这是一个数组对象
</>复制代码
function fn(...value){
console.dir(value);
value.slice() //可以使用数组的方法,区分arguments
}
fn(1,2,3,4,4)->[1,2,3,4,4]返回的是数组,可以使用数组的方法;
//无论形参是否有不定参数,arguments对象正常使用,反应传入的参数的数量
...扩展运算符 把运算符后面的数组,转为用逗号分开的参数序列;可以用在所有使用数组的的方法中
</>复制代码
console.log(1,2,3,4) //1 2 3 4;
console.log(...[1,2,3,4])//同上
//利用call的属性,转化数组
判断函数的调用,是直接调用还是new
</>复制代码
function A(a){this.a = a;}
var b = new A(3); //生成了对象
var c = A(4); //此时给全局属性添加了a=4
function A(a){
if(this instanceof A){this.a =a} //判断是否是new调用
else{return new A(a)}
}
var d = A.call(b,333) //通过call强制的指定this
//正确的写法
function B(b){
if(typeof new.target ! == "undefined"){this.b =b} //新的元属性
else{return new B(b)};
}
//es6可以在块级代码中,声明和使用函数,但是会作为全局函数
箭头函数 =>
</>复制代码
//当函数没有参数时;
var f1 = function(){ };//默认函数返回一个undefined;
var f1 = ( )=>{}; //空函数
var f2= ()=>"the value you want";
var f3 = ()=>{ //如果需要在函数体内执行多条代码,就必须用大括号包裹
doSomethings;
doantherthings;
return value; //必须用return 返回值;否则默认返回undefined;
}
//箭头函数有一个函数的时候
var f1 = function(arg1){
};
var f1 = arg1 =>undefined;
//箭头函数有多个参数的时候;
var f1 = function (arg1,arg2,arg3){
};
var f1 = (arg1,arg2,arg3)=> undefined;
var f2 = (arg1,arg2,arg3)=>arg1-arg2-arg3;
//注意如果箭头函数只是多带带的返回一个对象要在大括号的外面加个小括号;
var f1 = ()=>{
doSomething;
return { //此时不是多带带返回所以不需要
name : "name",
value : "value"
}
};
var f2 = ()=>({ //此时为了区分{}是否是函数体,所以要加上小括号;
name : "name",
value : "value"
})
//箭头函数的函数体内正常和一般函数一样,但是没有arguments数组对象,
//IIFE关于立即执行的函数
var f1 = (function(arg){
return {
getArg :function(){return arg}
}
})(arg) //返回对象的方法
var f1 = (arg=>{
return {
getArg :function(){return arg}
}
})("arg") //同上;
箭头函数的this指向问题 (this仅仅是外一层非箭头函数的函数this,否则就是undefined)
一般函数的this是根据调用的对象来指定的或者用new ,bind ,call 等操作符或者方法来绑定;
1,默认的this 指向
</>复制代码
function fn(){console.dir(this)} //此时默认的指向是window
2,隐式的this 指向
</>复制代码
var obj = {
name : "obama",
getName : function(){
return this.name //此时的指向是对象
}
}
3,new操作符
</>复制代码
function Name(name){
this.name = name;
}
var man = new Name("obama"); //此时指向的是new调用的对象
4,硬指定的this
</>复制代码
var getName= function(){
console.log(this.name)
}
var name = "bush";
var predents = {
name : "obama",
}
getName(); //bush
getName.call(preddents) //obama;
ES6的箭头函数this是和变量的作用域一样的词法指定(写在哪里就是那里的引用),不能更改,也不可以用new操作符,本着用完即丢的思想
</>复制代码
var a = ()=>this; //此时返回的是this对象是undefined;
var obj = {age : 45};
obj.b = a; //把函数a当作obj的方法;
obj.b() //正常不使用箭头函数的话, this的指向应该是调用的obj对象,但是这里显示的 是原来定义的window对象
a.call(obj) //显试的绑定,也不能改变this 的作用域;
var newa = new a() //报错,a不是一个构造函数;
如果要使用箭头函数的绑定的话在ES7里双冒号::左边是对象,右边的是方法,这样就可以绑定,
var foo = {age : 34};
var bar = ()=>this.age;
foo::bar
//以上仅作了解
尾调用优化特指函数的最后一步(一般函数最后一步默认是return undefined)这一步不能有其他任何的操作,比如赋值,算术运算 属于引擎的优化
一般JS引擎 在执行中,会进入执行上下文,全局,函数和eval上下文,三者中的一个,
保存这个上下文的地方就是在调用栈,栈的顶端就是一个变量对象,保存当前函数的使用的变量;
函数调用会在内存形成一个调用记录称之为调用帧,保存位置和内部变量,所有的调用帧就形成了一个调用栈;
尾调用因为是函数的一步,所以返回这个函数后,原函数就不必记住自己的变量,尾调用的函数会保存这个信息,所以内层的函数取代外部的函数,这样就行成优化
</>复制代码
function fn(){
let a = 1;
let b = 2;
return f2(a + b);
}
fn();
f2(3) //在函数fn里f2是尾调用,fn执行后,就不必记住自身可调用的变量,因为f2会记住执行;最终取代原函数;
function fn(num){ ///一般递归函数
if(num ===1){return 1};
return num+fn(num-1)
}
注意只有使用use strict 尾调用优化才会生效,而且argument 和caller 不能使用
</>复制代码
function fn(n,total=1){ //尾调用优化
if(n ===1) return total;
return fn(n-1,n+total)
}
//柯里化,将多参数的函数层层的使用单参数的函数调用
function add(n){
return curry(n,1)
};
function curry(n,total){
if(n ===1) return total;
return curry(n-1,n+total)
}
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/89125.html
摘要:之小白初入江湖超文本标记语言简称是一种用于创建网页的标准标记语言。描述了一个网站的结构语义随着线索的呈现,使之成为一种标记语言而非编程语言。是块级元素,是行内元素。层叠样式表简称是一种用来为结构化文档如添加样式的工具。 HTML & CSS之小白初入江湖 1. HTML 超文本标记语言(HyperText Markup Language, 简称HTML)是一种用于创建网页的标准标记语言...
摘要:之小白初入江湖超文本标记语言简称是一种用于创建网页的标准标记语言。描述了一个网站的结构语义随着线索的呈现,使之成为一种标记语言而非编程语言。是块级元素,是行内元素。层叠样式表简称是一种用来为结构化文档如添加样式的工具。 HTML & CSS之小白初入江湖 1. HTML 超文本标记语言(HyperText Markup Language, 简称HTML)是一种用于创建网页的标准标记语言...
摘要:刚开始做项目,正好碰上了一个批量下载的功能就是下面图片中的一个导出的功能后台返回的数据格式是这样的,如下做批量下载后台需要前端给一个必需字段,在我这里也就是上代码这样我们的就是一个由组成的数组,搞定 刚开始做vue项目,正好碰上了一个批量下载的功能 就是下面图片中的一个导出的功能showImg(https://segmentfault.com/img/bVbsuIr); 后台返回的数据...
摘要:本人前端萌新大概花了一周多一点,完成了一个前后端分离解耦的简易个人博客项目。项目前后端分离,路由完全交给处理,后端只负责操作数据库,暴露。目前项目提供做学习用途,希望能给大家一些帮助,对全栈项目有一个初步的了解,谢谢。 本人前端萌新大概花了一周多一点,完成了一个前后端分离解耦的简易个人博客项目。项目前后端分离,路由完全交给vue-router处理,后端只负责操作数据库,暴露api。 技...
阅读 1111·2023-04-26 02:21
阅读 2899·2021-09-24 09:47
阅读 1698·2019-08-30 15:55
阅读 2263·2019-08-30 14:01
阅读 2437·2019-08-29 14:01
阅读 2135·2019-08-29 12:46
阅读 900·2019-08-26 13:27
阅读 2060·2019-08-26 12:23