function 后面有函数名字的,不是直接跟括号的的就是具名函数。如果把一个具名函数赋值给一个变量,那么这个具名函数的作用域就不是 window 了(严格模式下 this 指向 undefined),且函数调用的名字也为变量名,对象中定义同理,不管有没有函数名称,最终调用的函数名均为此变量或属性名称。 具名函数的 this 指向是当我们调用函数的时候确定的,调用方式的不同决定了 this 不同的指向,一般指向我们的调用者。
let fun = functionfun1() { console.log('function1'); }; console.log(fun.name); // fun1 console.log(fun1.name); // Uncaught ReferenceError: fun1 is not defined fun(); // function1 fun1(); // Uncaught ReferenceError: fun1 is not defined
let obj = { fun: functiontest() { console.log(this.name); }, hello: function () { console.log('hello'); }, name: 'test' }; console.log(obj.fun.name); // test console.log(obj.hello.name); // hello obj.fun(); // test obj.hello(); // hello obj.fun.call({ name: 'hxb' }); // hxb test(); // Uncaught ReferenceError: test is not defined
箭头函数
箭头函数是 ES6 知识点,具有以下几个特点。
如果只有一个参数,可以省略小括号。
如果有至少有两个参数,必须加小括号。
如果函数体只有一句话可以省略花括号,并且这一句作为返回值 return。
如果函数体至少有两句必须加上花括号。
箭头函数没有自己的 this,它的 this 继承于运行时的外层代码库的第一个 this,由上下文决定,所以也不能用call、apply、bind 去改变 this 的指向。
functionKing() { if (!new.target) { throw'King must be instantiated using "new"'; } console.log('King instantiated using "new"'); } newKing(); // King instantiated using "new" King(); // Error: King must be instantiated using "new"
functionWidget() { let data = {}; return { get: function (key) { return data[key]; }, set: function (key, value) { data[key] = value; return data[key]; } }; }
let test = newWidget(); test.set('name', 'hxb'); console.log(test.get('name')); // hxb console.log(data['name']); // Uncaught ReferenceError: data is not defined
for (var i = 1; i <= 5; i++) { setTimeout(functiontimer() { console.log(i); }, i * 1000); } // 怎样可以使得上述代码的输出变为 1,2,3,4,5? // 我们可以把 var 换成 let 实现 for (let i = 1; i <= 5; i++) { setTimeout(functiontimer() { console.log(i); }, i * 1000); } // 也可以使用闭包来实现 for (var i = 1; i <= 5; i++) { (function (i) { setTimeout(functiontimer() { console.log(i); }, i * 1000); })(i); }
根据上面的说法,将闭包看成一个背包,背包中包含定义时的变量,每次循环时,将 i 值保存在一个闭包中,当 setTimeout 中定义的操作执行时,则访问对应闭包保存的 i 值,即可解决。
Function 的 prototype 指向一个特殊匿名函数,而这个特殊匿名函数的 _proto_ 指向Object.prototype。
顺便发一下原型链图
关于复杂对象与 new function/new Function
函数的使用与复杂对象
函数是 JavaScript 中很重要的一个语言元素,并且提供了一个 function 关键字和内置对象 Function,下面是其可能的用法和它们之间的关系。
使用方法一
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
let func = function () { let test = 100; this.test = 200; return test + this.test; }; console.log(typeof func); // function console.log(func()); // 300 // 或者 let test = 200; let func = function () { let test = 100; return test + this.test; }; console.log(typeof func); // function console.log(func()); // 300
最普通的 function 使用方式,定一个 JavaScript 函数。在大扩号内的变量作用域中,this 指代 func 的所有者,即window对象。
使用方法二
1 2 3 4 5 6 7 8 9
let test = 300; let func = new (function () { let test = 100; this.test = 200; return test + this.test; })(); console.log(test); // 300 console.log(typeof func); // object console.log(func.constructor()); // 300
创建一个函数对象的语法是 let func = new Function([arg1, arg2, ...argN], functionBody); 其中,该函数对象的 N 个参数放在函数主体参数 functionBody 的前面,即函数主体参数必须放在参数列表的最后,也可以无参数 new Function(functionBody)。
1 2 3 4 5
let sum = newFunction('a', 'b', 'return a + b'); let sayHi = newFunction('console.log("Hello")');