利趣网站开发商,国内服装电商平台,中国建设网官方网站,淘宝关键词工具函数声明方式 匿名函数 function后面直接跟括号#xff0c;中间没有函数名的就是匿名函数。 let fn function() {console.log(我是fn)
}
let fn2 fn
console.log(fn.name) //fn
console.log(fn2.name)//fn#xff0c;fn和fn2指向的是同一个function。
复制代码具名函数 fun…函数声明方式 匿名函数 function后面直接跟括号中间没有函数名的就是匿名函数。 let fn function() {console.log(我是fn)
}
let fn2 fn
console.log(fn.name) //fn
console.log(fn2.name)//fnfn和fn2指向的是同一个function。
复制代码具名函数 function后面有函数名字的不是直接跟括号的的就是具名函数。 如果把一个具名函数赋值给一个变量那么这个具名函数的作用域就不是window了。 let fn function fn1() {console.log(function)
}
console.log(fn.name) //fn1
console.log(fn1,name) // ReferenceError: fn1 is not defined
复制代码箭头函数 箭头函数是es6知识点具有以下几个特点 如果只有一个参数可以省略小括号。如果有至少有两个参数必须加小括号。如果函数体只有一句话可以省略花括号并且这一句作为返回值return。如果函数体至少有两句必须加上花括号。箭头函数里面是没有this的。let fn e e1
console.log(fn(1)) //2let fn1 (i,y) iy
console.log(fn1(2,3)) //5let fn2 (i,y) {i1;y2;return iy
}
console.log(fn2(5,6)) //13
复制代码词法作用域静态作用域 静态作用域又叫做词法作用域采用词法作用域的变量叫词法变量。词法变量有一个在编译时静态确定的作用域。词法变量的作用域可以是一个函数或一段代码该变量在这段代码区域内可见visibility在这段区域以外该变量不可见或无法访问。词法作用域里取变量的值时会检查函数定义时的文本环境捕捉函数定义时对该变量的绑定。 词法作用域变量的作用域是在定义时决定而不是执行时决定也就是说词法作用域取决于源码通过静态分析就能确定因此词法作用域也叫做静态作用域。 with和eval除外所以只能说JS的作用域机制非常接近词法作用域Lexical scope。 通过词法作用域树能判断变量指向关系但是不能断定变量的值变量的值还需要根据执行顺序进一步作出判断看一下例子 因为JavaScript采用的是词法作用域bianliang的作用域基于函数创建的位置跟调用时的位置无关。 var i 1,j 2,k 3;function a(o, p, x, q) {var x 4;alert(i);function b(r, s) {var i 11,y 5;alert(i);function c(t) {var z 6;alert(i);};var d function() {alert(y);};c(60);d();};b(40, 50);
}
a(10, 20, 30); //1 11 11 5
复制代码/**
* 模拟建立一棵语法分析树存储function内的变量和方法
*/
var SyntaxTree {// 全局对象在语法分析树中的表示window: {variables:{i:{ value:1},j:{ value:2},k:{ value:3}},functions:{a: this.a}},a:{variables:{x:undefined},functions:{b: this.b},scope: this.window},b:{variables:{i:undefinedy:undefined},functions:{c: this.c,d: this.d},scope: this.a},c:{variables:{z:undefined},functions:{},scope: this.b},d:{variables:{},functions:{},scope: {scope: this.b}}
};
复制代码/**
* 活动对象函数执行时创建的活动对象列表
*/
let ActiveObject {window: {variables: {i: { value: 1 }j: { value: 2 }k: { value: 3 }},functions: {a: this.a}}a: {variables: {x: { vale: 4 },functions: {b this.b},scope: this.window,params: {o: { value: 10 },p: { value: 20 },x: this.variables.xq: { vale: undefined }},arguments: [this.params.o, this.params.p, this.params.x]}}b: {variables: {i: { vale: 11 },y: { vale: 5 },},functions: {c: this.c,d: this.d},params: {r: { value: 40 }s: { value: 50 }},arguments: [this.params.r, this.params.scope]scope: this.a}c: {variables: {z: { value: 6 },functions: {},params: {t: { value: 60 }},arguments: [this.params.t]scope: this.b}}d: {variables: {},functions: {},params: {},arguments: []this.scope: this.b}}
复制代码call stack 进入call stack 时的一些规则 函数的所有形参(如果我们是在函数执行上下文中) 由名称和对应值组成的一个变量对象的属性被创建没有传递对应参数的话那么由名称和 undefined 值组成的一种变量对象的属性也将被创建。 所有函数声明(FunctionDeclaration, FD) 由名称和对应值函数对象(function-object)组成一个变量对象的属性被创建如果变量对象已经存在相同名称的属性则完全替换这个属性。 所有变量声明(var, VariableDeclaration) 由名称和对应值undefined组成一个变量对象的属性被创建如果变量名称跟已经声明的形式参数或函数相同则变量声明不会干扰已经存在的这类属性。/*
* example1:形参
*/
function test(a, b) {/*var a 10var b undefined根据规则1在进入执行上下文时会自动对形参声明并且赋值。*/ console.log(a)var c 10;function d() {}var e function _e() {};(function x() {});
}
test(10); // 10
复制代码/*
* example2:函数声明
*/
function test(a, b) {console.log(a)function a() {}var e function _e() {};
}
test(10); // ƒ a() {} .根据规则2进入执行上下文会自动声明形参并且赋值但是同名的函数声明会替换这个变量。function test(a, b) {console.log(a)var a 30;var a function _e() {};
}
test(10); // 10 .根据规则2进入执行上下文会自动声明形参并且赋值但是同名的函数声明会替换这个变量。
复制代码/*
* example3:变量声明
*/
console.log(foo);//会打印出foo函数根据规则3同名的变量声明不会干扰函数声明和形参function foo(){console.log(foo);
}var foo 1;
复制代码this和arguments 函数调用 在es5中函数有四种调用方式 1. fn(p1,p2)
2. obj.fn(p1,p2)
3. fn.call(context,p1,p2)
4. fn.apply(context,p1,p2)
复制代码第三和第四种才是正常的js函数调用方式其他两种就是语法糖。 fn(p1,p2) 等价于 fn.call(undefined,p1,p2) 等价于 fn.apply(context,[p1,p2])
obj.fn(p1,p2) 等价于 obj.fn.call(obj,p1,p2) 等价于 obj.fn.apply(obj,[p1,p2])
复制代码 如果你传的 context 就 null 或者 undefined那么 window 对象就是默认的 context严格模式下默认 context 是 undefined this是什么 this是call的第一个参数 var obj {foo: function(){console.log(this)}
}var bar obj.foo
obj.foo() // 打印出的 this 是 obj
bar() // 打印出的 this 是 window
复制代码obj.foo() 相当于 obj.foo.call(obj) 也就相当于把函数名前面的作为call的第一个参数也就是this如果没有就是window。
bar() 相当于 bar.call(undefined)
复制代码在执行函数的时候this是隐藏的一个参数且必须是一个对象如果不是js是自动把它转为对象。 function fn() {console.log(this)console.log(arguments)
}
fn.call(1,2,3) // Number {1} [2,3]
复制代码arguments arguments是伪数组它类似于Array但除了length属性和索引元素之外没有任何Array属性。 call和apply里面除了第一个参数之外的都是arguments如果arguments的个数少建议使用call使用apply也可以如果不确定就使用apply。 使用一下方法吧arguments转为真正的数组 var args Array.prototype.slice.call(arguments);
var args [].slice.call(arguments);// ES2015
const args Array.from(arguments);
const args [...arguments]
复制代码bind MDN 官方文档对 bind() 的定义: The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called. 大概意思就是bind会返回一个新的函数并没有的调用原来的函数这个新函数会call原来的函数call的参数由你决定。看例子 this.x 9;var module {x: 81,getX: function() { return this.x; }};var retrieveX module.getX;var boundGetX retrieveX.bind(module);boundGetX(); // 81
复制代码retrieveX.bind(module)返回了一个新的函数boundGetX,然后调用这个新的函数的时候把这个函数里面的this绑定到了module对象上所以this.x就相当于module.x也就是等于81. 柯里化 在计算机科学中柯里化英语Currying又译为卡瑞化或加里化是把接受多个参数的函数变换成接受一个单一参数最初函数的第一个参数的函数并且返回接受余下的参数而且返回结果的新函数的技术。这个技术由克里斯托弗·斯特雷奇以逻辑学家哈斯凯尔·加里命名的尽管它是Moses Schönfinkel和戈特洛布·弗雷格发明的。 说的明白一点就是给函数传递一部分参数让它返回一个函数去处理其他参数举个例子求三个数之和 let addOne function add(x) {return function(y) {return function(z) {return xyz}}
}let one addOne(3)
console.log(one)//ƒ (y) {return function (z) {return x y z}}
let two one(4)
console.log(two)//ƒ (z) {return x y z}
let three two(5)
console.log(three)//12
复制代码javascript函数柯里化--详细说明链接 高阶函数 在数学和计算机科学中高阶函数是至少满足下列一个条件的函数 接受一个或多个函数作为输入输出一个函数 举一些高阶函数的例子 /*
*接受一个或多个函数作为输入
*/
1. Array.prototype.filter()
2. Array.prototype.forEach()
3. Array.prototype.reduce()
4. Array.prototype.map()
5. Array.prototype.find()
6. Array.prototype.every()
复制代码/*
*输出一个函数
*/
1. fn.bind(args)
复制代码回调函数 函数A作为参数(函数引用)传递到另一个函数B中并且这个函数B执行函数A。我们就说函数A叫做回调函数。如果没有名称(函数表达式)就叫做匿名回调函数。 名词形式被当做参数的函数就是回调 动词形式调用这个回调 注意回调跟异步没有任何关系 回调函数的使用场合 资源加载动态加载js文件后执行回调加载iframe后执行回调ajax操作回调图片加载完成执行回调AJAX等等。 DOM事件及Node.js事件基于回调机制(Node.js回调可能会出现多层回调嵌套的问题)。 setTimeout的延迟时间为0这个hack经常被用到settimeout调用的函数其实就是一个callback的体现 链式调用链式调用的时候在赋值器(setter)方法中(或者本身没有返回值的方法中)很容易实现链式调用而取值器(getter)相对来说不好实现链式调用因为你需要取值器返回你需要的数据而不是this指针如果要实现链式方法可以用回调函数来实现。 setTimeout、setInterval的函数调用得到其返回值。由于两个函数都是异步的即他们的调用时序和程序的主流程是相对独立的所以没有办法在主体里面等待它们的返回值它们被打开的时候程序也不会停下来等待否则也就失去了setTimeout及setInterval的意义了所以用return已经没有意义只能使用callback。callback的意义在于将timer执行的结果通知给代理函数进行及时处理。 回调函数的传递 传递的方式有两种函数引用和函数表达式。 $.get(myhtmlpage.html, myCallBack);//这是对的
$.get(myhtmlpage.html, myCallBack(foo, bar));//这是错的那么要带参数呢
$.get(myhtmlpage.html, function(){//带参数的使用函数表达式
myCallBack(foo, bar);
});
复制代码箭头函数与es5的函数主要区别 箭头函数的主要区别在this箭头函数是没有this这个概念的看例子 setTimeout(function(a){console.log(this) //这个this指的是{name:Jack}setTimeout(function(a){console.log(this) //这个this指的是window因为没有bind调用setTimeout的是window},1000)
}.bind({name:Jack}),1000)
复制代码setTimeout(function(a){console.log(this) //这个this指的是{name:Jack}setTimeout(function(a){console.log(this) //这个this指的是{name: Jack}因为bind了外面的this也就是{name: Jack}},1000)
}.bind({name:Jack}),1000)
复制代码setTimeout(function(a){console.log(this) //这个this指的是{name:Jack}setTimeout(aconsole.log(this),1000)//这个this指的是{name:Jack},因为箭头函数没有this的概念它指的this就是外面的this也就是{name:Jack}
}.bind({name:Jack}),1000)
复制代码至此基本上说了js的所有函数内容只是简单举个例子更深入的研究还需要看一些其他大佬的博客哦~~~~ 转载于:https://juejin.im/post/5aa5ad0af265da237a4ca4f5