add: 函数的定义

This commit is contained in:
qianguyihao 2019-12-10 22:39:08 +08:00
parent 0ff9b66135
commit 0bbb6c66de
6 changed files with 163 additions and 22 deletions

View File

@ -1,4 +1,21 @@
## 前言
关于函数的核心内容:
- 函数有哪几种定义和调用方式
- this函数内部的 this 指向、如何改变 this 的指向。
- 函数的严格模式
- 高阶函数:函数作为参数传递、函数作为返回值传递
- 闭包:闭包的作用
- 递归:递归的两个条件
- 深拷贝和浅拷贝的区别
## 函数的介绍
@ -27,13 +44,13 @@ function sayHello(){
}
```
## 函数的定义
## 函数的定义和调用
### 方式一:函数声明(命名函数)
### 第一步:函数的定义
**方式一**使用`函数声明`来创建一个函数。语法:
使用`函数声明`来创建一个函数(也就是 function 关键字)。语法:
```javascript
@ -45,7 +62,7 @@ function 函数名([形参1,形参2...形参N]){ // 备注:语法中的中括
举例:
```javascript
function sum(a, b){
function fun1(a, b){
return a+b;
}
```
@ -62,10 +79,12 @@ function sum(a, b){
PS在有些编辑器中方法写完之后我们在方法的前面输入`/**`,然后回车,会发现,注释的格式会自动补齐。
**方式二**:使用`函数表达式`来创建一个函数。语法:
### 方式二:函数表达式(匿名函数)
使用`函数表达式`来创建一个函数。语法:
```javascript
var 函数名 = function([形参1,形参2...形参N]){
var 变量名/函数名 = function([形参1,形参2...形参N]){
语句....
}
```
@ -73,17 +92,59 @@ var 函数名 = function([形参1,形参2...形参N]){
举例:
```javascript
var fun3 = function() {
var fun2 = function() {
console.log("我是匿名函数中封装的代码");
};
```
从方式二的举例中可以看出:所谓的“函数表达式”,其实就是将匿名函数赋值给一个变量。
当然,我们还有方式三:使用构造函数来创建一个对象。这种方式,用的少。
### 方式三:使用构造函数 new Function()
### 第二步:函数的调用
使用构造函数`new Function()`来创建一个对象。这种方式,用的少。
语法:
```javascript
var 变量名/函数名 = new Function('形参1', '形参2', '函数体']);
```
注意,这里是直接将函数体放在**字符串**里包裹起来,放在 Function 的最后一个参数的位置;而且,形参也必须放在**字符串**里。
代码举例:
```javascript
var fun3 = new Function('a', 'b', 'console.log("我是函数内部的内容"); console.log(a + b);');
fun3(1, 2); // 调用函数
```
打印结果:
```
我是函数内部的内容
3
```
**分析**
方式3的写法很少用原因如下
- 不方便书写:写法过于啰嗦和麻烦。
- 执行效率较低:首先需要把字符串转换为 js 代码,然后再执行。
### 总结
1、**所有的函数,都是 `Fuction` 的“实例”**(或者说是“实例对象”)。函数本质上都是通过 new Function 得到的。
2、函数既然是实例对象那么**函数也属于“对象”**。还可以通过如下特征,来佐证函数属于对象:
- 我们直接打印某一个函数,比如 `console.log(fun2)`,发现它的里面有`__proto__`。(这个是属于原型的知识,后续再讲)
- 我们还可以打印 `console.log(fun2 instanceof Object)`,发现打印结果为 `true`。这说明 fun2 函数就是属于 Object。
## 函数的调用
函数调用的语法:
@ -267,6 +328,11 @@ function fn(){
我们可以这样说,如果直接是`fn()`,那就说明是函数调用。如果是`XX.fn()`的这种形式,那就说明是**方法**调用。
## 构造函数、原型对象、对象实例之间的关系
暂略。
## 我的公众号
想学习<font color=#0000ff>**代码之外的技能**</font>?不妨关注我的微信公众号:**千古壹号**id`qianguyihao`)。

View File

@ -3,7 +3,8 @@
## 作用域Scope的概念
作用域是一个变量或函数的作用范围。作用域在**函数定义**时,就已经确定了。
通俗来讲,作用域是一个变量或函数的作用范围。作用域在**函数定义**时,就已经确定了。
### 作用域的分类
@ -13,7 +14,10 @@
- 函数作用域
在函数作用域中可以访问到全局作用域的变量,在全局作用域中无法访问到函数作用域的变量。
### js 是函数级别作用域
js 是函数级别作用域:在内部作用域中可以访问到外部作用域的变量,在外部作用域中无法访问到内部作用域的变量。
代码举例:
@ -32,11 +36,7 @@ console.log(b); // 报错Uncaught ReferenceError: b is not defined。说明
定义在函数作用域的变量,叫「局部变量」。
### 执行上下文
当**函数执行**时,会创建一个执行期上下文的内部对象。每调用一次函数,就会创建一个新的上下文对象,他们之间是相互独立的。当函数执行完毕,它所产生的执行期上下文会被销毁。参考链接:<https://www.cnblogs.com/chenyingjie1207/p/9966036.html>
**作用域的上下级关系:**
### 作用域的上下级关系
当在函数作用域操作一个变量时,它会先在自身作用域中寻找,如果有就直接使用(**就近原则**)。如果没有则向上一级作用域中寻找,直到找到全局作用域;如果全局作用域中依然没有找到,则会报错 ReferenceError。
@ -84,6 +84,24 @@ console.log(b); // 报错Uncaught ReferenceError: b is not defined。说明
![](http://img.smyhvae.com/20180314_2136.png)
举例3
```javascript
foo();
function foo() {
if (false) {
var i = 123;
}
console.log(i);
}
```
打印结果undefined。注意打印结果并没有报错而是 undefined。这个例子再次说明了变量 i 在函数执行前,就被提前声明了,只是尚未被赋值。
打印结果:
### 函数的声明提前
**函数声明**
@ -136,7 +154,7 @@ console.log(b); // 报错Uncaught ReferenceError: b is not defined。说明
```
上方代码中,foo()的打印结果是`1`。如果去掉第一行代码,打印结果是`Uncaught ReferenceError: a is not defined`
上方代码中,执行foo()后,打印结果是`1`。如果去掉第一行代码,打印结果是`Uncaught ReferenceError: a is not defined`
**提醒2**:定义形参就相当于在函数作用域中声明了变量。

View File

@ -0,0 +1,35 @@
## 一些概念
### 作用域和作用域链
**作用域**
每个 JS 函数都是一个对象,对象中有些属性我们可以访问,有些属性我们不可以访问。无法访问的这些属性仅供 JS 引擎存取,[[scope]] 属性就是其中之一。
[[scope]]就是我们所说的作用域,其中存储了执行期上下文的集合。
**作用域链**
[[scope]]中所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。
### 执行期上下文
当**函数执行**时(准确来说,是在函数发生预编译的前一刻),会创建一个执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境。
每调用一次函数,就会创建一个新的上下文对象,他们之间是相互独立且独一无二的。当函数执行完毕,它所产生的执行期上下文会被销毁。
## 最后一段
备注:本文的内容还有待完善。
## 参考链接
- <https://www.cnblogs.com/chenyingjie1207/p/9966036.html>

View File

View File

@ -79,10 +79,32 @@ window.open('你所要跳转的新页面');
```
### 2019-12-10-JavaScript 新特性Optional Chaining可选链式调用语法
以往写代码,我们一般都这么写:
```javascript
if (result && result.user && result.user.name && result.user.name.length) {
console.log('qianguyihao');
}
```
有了 Optinal Chain 语法之后,就简洁很多了,可以这么写:
```javascript
if (result?.user?.name?.length) {
console.log('qianguyihao');
}
```
参考链接:
- 了解 JavaScript 新特性Optional Chaining<https://www.infoq.cn/article/2JDORgXrU6VmZ7jlyuFD>
- 原文链接: https://v8.dev/features/optional-chaining