函数声明
// 普通函数表达式
var aaa = function () {};
// 箭头函数表达式
const func = () => {};
// 命名函数表达式
var bbb = function f() {};
// 函数声明
function ccc() {}
- 函数声明可以提前被解析出来,而表达式不可以。
解析器会先读取函数声明,并使其在执行任何代码之前可以访问,在任何地方调用都不会有问题;
而函数表达式则必须等到解析器执行到它所在的代码行才会真正被执行,提前调用会报错
aaa(); //会报错--aaa is not a function
ccc(); //可以调用
var aaa = function(){};
function ccc(){}
- 函数表达式可以直接后面加括号执行,而函数声明是不可以。
var aaa = function () {
}();//可以直接执行
function ccc() {
}()//会报错
当同时使用这两种方式声明同一个函数名,最终执行的是函数表达式声明的函数
// 函数表达式
var f = function () {
console.log(1);
}
// 直接声明
function f() {
console.log(2);
}
f();//控制台打印1
自执行函数
自执行函数严格来说也叫函数表达式,它主要用于创建一个新的作用域,在此作用域内声明的变量,不会和其它作用域内的变量冲突或混淆,大多是以匿名函数方式存在,且立即自动执行。
//可用来传参
(function (x, y) {
console.log(x + y);
})(2, 3);
//带返回值
var sum = (function (x, y) {
return x + y;
})(2, 3);
console.log(sum);
~function () {
var name = '~';
console.log(name);
}();
!function () {
var name = '!';
console.log(name);
}();
;(function () {
var name = ';';
console.log(name);
})();
-function () {
var name = '-';
console.log(name);
}();
//逗号运算符
1, function () {
var name = ',';
console.log(name);
}();
//异或
1 ^ function () {
var name = '^';
console.log(name);
}();
//比较运算符
1 > function () {
var name = '>';
console.log(name);
}();
~+-!(function () {
var name = '~+-!';
console.log(name);
})();
~!(function () {
var name = '~!';
console.log(name);
})();
(function () {
var name = 'call';
console.log(name);
}).call();
(function () {
var name = 'apply';
console.log(name);
}).apply();
函数构造法,参数必须加引号
var sum3 = new Function('n1', 'n2', 'return n1+n2');
console.log(sum3(2, 3));//5
从技术角度讲,这是一个函数表达式。一般不推荐用这种方法定义函数,因为这种语法会导致解析两次代码(第一次是解析常规ECMAScript代码,第二次是解析传入构造函数中的字符串),从而影响性能。
var name = 'hello';
function fun() {
var name = 'world';
return new Function('return name');//不能获取局部变量
}
console.log(fun()());//控制台打印hello
Function()构造函数每次执行时都会解析函数主体,并创建一个新的函数对象,所以当在一个循环或频繁执行的函数中调用Function()构造函数效率是非常低的。而函数字面量却不是每次遇到都会重新编译的,用Function()构造函数创建一个函数时并不遵循典型的作用域,它一直把它当作是顶级函数来执行。
this(执行上下文)指向
1.普通函数中的this
- 在简单调用中,非严格模式下,指向window。严格模式下,为undefined。
function parent() {
console.log(this);
}
parent(); // window
'use strict';
function parent() {
console.log(this);
}
parent(1,2); // undefined
- 作为某个对象方法调用时,this指向该对象。
- 当该普通函数被间接调用时,即:使用
call()
和apply()
方法调用时,this指向call()
和apply()
第一个参数。注意:在非严格模式下, 当第一个参数为null
或者undefined
时,调用函数中的this指向window
哦~~~
function parent() {
console.log(this);
}
const obj = {
name: 'ha'
}
parent.call(obj); // this指向obj对象
- 该普通函数被用作构造函数用new关键字构造对象实例时,this指向新建的实例。
2.箭头函数中的this
- 没有自己的this,内部this的值,依赖于外部非箭头函数的this。
function regular() {
console.log(this);
const arrowFun = () => {
console.log(this); // obj
}
arrowFun();
}
const obj = {
name: 'ha'
}
regular.call(obj);
构造函数
普通函数
- 普通函数可以作为构造函数来用,用new去新建对象实例。
- 普通函数内部,arguments为特殊的类数组对象。包含了函数被调用时的参数列表。
- 用return去返回一个函数的结果。无return语句,或者return后面无表达式,则返回undefined
- 由于普通函数的this,由执行时候确定。那么当做为定时器函数或者事件监听器的回调去执行时,就有this指向的问题了。这时候,你或许需要用bind()方法去绑定this值。
https://blog.csdn.net/qq_40713392/article/details/106319971
http://www.itcast.cn/news/20200908/17231826697.shtml
https://blog.csdn.net/weixin_30655569/article/details/101788084