立即执行函数
- 代码
(function () { // ... })();
- 创建函数的同时立即执行,没有绑定任何事件,也无需等待任何异步操作
-
function () {}
是一个匿名函数,包围它的一对括号将其转换为一个表达式,紧跟其后的一对括号调用了这个函数。立即执行函数也可以理解为立即调用一个匿名函数。最常见的应用场景就是:将变量的作用于限制于函数内,避免命名冲突。 - 实现代码模块化。
闭包
- 概念
- 定义在函数内部,能够访问其他函数局部变量的函数。
- 只有函数内部的子函数才能读取局部变量,因此可以把闭包理解成
定义在一个函数内部的函数
。
- 闭包的作用
- 通过闭包可以在函数外部访问函数内部的变量,闭包将函数外部和内部进行了链接。
- 使用闭包之后,外部函数的变量就会被存在内存中,不会被垃圾回收机制回收。
- 闭包让你可以在一个内层函数中访问到其外层函数的作用域。MDN 闭包
- 在 JavaScript 中,闭包会随着函数的创建而被同时创建。
- 当外部函数返回之后,内部函数依然可以访问外部函数的变量。
function f1() { let n = 0; // f2() 是内部函数,一个闭包 function f2() { n += 1; // 使用了父函数中声明的变量 alert(n); } return f2; } let f = f1(); f();
-
f1()
创建了一个局部变量n
和一个名为f2()
的函数。f2()
是定义在f1()
里的内部函数,并且仅在f1()
函数体内可用。f2()
没有自己的局部变量,因为它可以访问到外部函数的变量,所以f2()
可以使用父函数f1()
中声明的变量n
。 - 词法作用域根据源代码中声明变量的位置来确定该变量在何处可用。嵌套函数可访问声明于它们外部作用域的变量。
-
使用闭包定义私有变量
function P() {
let name;
this.setName = function(value) {
name = value;
}
this.getName = function() {
return name;
}
}
let p = new P();
p.setName("Func");
console.log(p.name); // undefined
console.log(p.getName()); // Func
prototype
- 每个 JavaScript 的构造函数都有一个
prototype
属性,用于设置所有实例对象需要共享的属性和方法。 -
prototype
属性不能列举。 - JavaScript 仅支持通过
prototype
属性进行继承属性和方法。function Func(x, y) { this.length = x; this.width = y; } Func.prototype.getDimensions = function() { return { length: this.length, width: this.width } } let x = new Func(3, 4); let y = new Func(5, 6); console.log(x.getDimensions()); console.log(y.getDimensions());
变量提升
- 函数首先被提升,然后才是变量。
- 函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。
- 当变量(仅声明未初始化或赋值)和函数同名时,引用变量名(函数名)的位置如果是在变量被赋值之前,那么此时引用的就是函数;如果引用是在变量赋值之后,那么引用的就是变量。
- 函数声明和变量声明提升以及优先级
柯里化
- 让函数变得更加灵活,可以一次性传入多个参数调用它,也可以只传一部分参数,让它返回一个函数去处理剩下的参数
let add = function(x) { return function(y) { return x + y; } } console.log(add(1)(1)); // 2 let add1 = add(1); console.log(add1(2)); // 3
函数重载
- 理解下面代码需要知道一个知识点
let len = (function() {}).length; console.log(len); // 0 let len1 = (function(a) {}).length; console.log(len1); // 1 let len2 = (function(a, b) {}).length; console.log(len2); // 2
- 一个
function
直接.length
返回的是函数期望传入的参数数量,即形参的个数。
- 一个
-
function addMethod(object, name, f) { let old = object[name]; object[name] = function() { if (f.length == arguments.length) { return f.apply(this, arguments); } else if (typeof old == "function") { return old.apply(this, arguments); } } } function find0() { return this.names; } function find1(firstName) { let result = []; for (let i = 0; i < this.names.length; i++) { if (this.names[i].indexOf(firstName) == 0) result.push(this.names[i]); } return result; } function find2(firstName, secondName) { let result = []; for (let i = 0; i < this.names.length; i++) { if (this.names[i] == firstName + " " + secondName) result.push(this.names[i]); } return result; } let people = {names: ["Tom Jerry", "Tom Dog", "Jerry Dog"]}; addMethod(people, "find", find0); addMethod(people, "find", find1); addMethod(people, "find", find2); console.log(people.find()); // 调用 find0 console.log(people.find("Tom")); // 调用 find1 console.log(people.find("Tom", "Jerry")); // 调用 find2
- 从效果上来说,
people
对象的find
方法允许 3 种不同的输入:0 个参数时,返回所有人名;1 个参数时,根据 firstname 查找人名并返回;2 个参数时,根据完整的名称查找人名并返回。 - 难点在于,
people.find
只能绑定一个函数,那它为何可以处理3种不同的输入呢? - 就此片段中
addMethod
函数的调用顺序可知,people.find
最终绑定的是find2
函数,然而在绑定find2
时,old
为find1
;绑定find1
时,old
为find0
。3 个函数通过闭包链接起来。
- 从效果上来说,
文章来源地址https://www.toymoban.com/news/detail-682243.html
文章来源:https://www.toymoban.com/news/detail-682243.html
到了这里,关于JavaScript 知识点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!