Jacky's blog Jacky's blog
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Jacky Wang

行到水穷处,坐看云起时
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 常用资源导航
  • 概念
  • 代码格式化
  • 面向对象基础
  • 构造函数与原型
  • 函数进阶
    • 1.万物皆对象
    • 2. 函数中this的默认指向
    • 3.改变this指向
      • call()
      • apply()
      • bind()
      • call apply bind总结
    • 4.高阶函数
    • 5.闭包
    • 6.浅拷贝与深拷贝
  • 函数柯里化
  • 函数-传参
  • axios
  • Node 和 ES6 模块系统
  • JS
wangjiasheng
2021-01-09
目录

函数进阶

# 1.万物皆对象

JavaScript中基本所有都是对象,函数也是一个对象

函数的定义

//1.正常创建
function fn(){}
//2.匿名表达式 + 定义新变量
var fn = function(){}
//3.形参写法:new Function('参数1','参数2','函数体')
var fn = new Function('a','b','console.log(a+b)');
fn(1,2);
1
2
3
4
5
6
7

六种调用方式

//1.普通函数
function fn(){console.log('人生的巅峰')};
fn();
//2.对象调用
var obj = {
    sayHi:function(){console.log('hello world!')};
}
obj.sayHi();
//3.构造函数
function Star(){};
new Star();
//4.绑定事件函数
btn.onclick = function(){};
//5.定时器函数
setInterval(function(){},1000);
//6.立即执行函数,()()
(function(){})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 2. 函数中this的默认指向

调用方式 this指向
function(){} window
new 构造函数 取决于实例对象
对象调用obj.sayHi() 取决于obj
setInterval(function(){},1000) window
(function(){})() window

# 3.改变this指向

# call()

功能:直接调用,改变this的指向

fn.call(this,arg1,arg2,...);
1

# apply()

功能:使用同call,区别在于输入的必须是数组或伪数组

fn.apply(this,[arg1,arg2,...]);
               
// 应用场景,可以帮助取出[]
// 如:Math.max只能接受数字型1,2,3,而通过apply可以很简单的将数组取出,类似ES6中的扩展符...
array = [1 ,2 ,55, 99];
let maxNum1 = Math.max.apply(Math,array);//第一个参数是指针对象,Math是调用max函数的这个对象
let maxNum2 = Math.max(...array);
1
2
3
4
5
6
7

# bind()

功能:调整this的指向,但是不立即执行,非常常用的函数

⚠️注:返回由指定的this值和初始化参数改造的原函数的拷贝;

let o = {
    name: 'andy'
}
function fn(a,b){
    console.log(a + b);
}
let f = fn.bind(o,1,2); // 绑定时不执行
f(); // 后执行
1
2
3
4
5
6
7
8

# call apply bind总结

  1. call经常做继承
  2. apply经常跟数组有关系,比如借助数学对象实现最大值和最小值
  3. bind 不调用函数,但是还想改变this指向,比如改变定时器内部this指向

# 4.高阶函数

高阶函数是对其他函数进行操作的函数,分两类,将函数进行输入或将函数进行输出。

  • 函数作为输入[典型:回调函数]
// 方式一:将函数进行输入,最典型的就是作为回调函数
function fn(a,b,callback){
    console.log(a+b);
    callback && callback(); // 很巧,如果有,才去执行callback
}

// 经典回调函数
$("div").animate({left: 500},function(){
    $("div").css("backgroundColor","purple");
});
1
2
3
4
5
6
7
8
9
10
  • 函数作为输出[return function(){}] [典型:闭包]
// 方式二:return function
function fn(){
    return function(){};
};
fn();
1
2
3
4
5

# 5.闭包

变量作用域分两类:

  • 全局变量:函数内部可以。
  • 局部变量:函数外部不可使用,且执行完毕后,局部变量会销毁。

闭包(closure):是指有权访问另一个函数作用中变量的函数

闭包的简单实现:

// 最简单的闭包:[内访外]内部函数可以访问外部函数的变量
function fn1(){
    var num = 10;
    function fn2(){
        console.log(num);// 10
    }
    fn2();
}
fn1();

// [外访内]fn1函数外部访问fn1中的变量
function fn1(){
    var num = 10;
    return function(){
        console.log(num);
    }
}
var f = fn();
f();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

⚠️注意:难点主要在外访内

  • 外访内时,第一步var f = fn()是取出return中的内部函数

  • 内部函数需要调用外部函数中的变量num,所以如果f()没有调用,则局部变量暂时不会销毁,此时我们称fn1为闭包函数。

点击查看

闭包的三个案例

  • 循环点击事件
<ul class="nav">
    <li>榴莲</li>
    <li>臭豆腐</li>
    <li>大猪蹄子</li>
    <li>鲱鱼罐头</li>
</ul>
<script>
	var lis = document.querySelector('.nav').querySelectorAll('li');
    // 1. 循环绑定onclick
    for(let i=0;i<lis.length;i++){
        lis[i].index = i;
        lis[i].onclick = function(){
            console.log(this.index);
        }
    }
    // 2. 利用闭包的方式得到索引号
    for(let i=0;i<lis.length;i++){
        // 外部函数:立即执行函数
        // 内部函数:绑定在button按钮上,立即函数
        // 外部变量: i索引
        (function(i){
			lis[i].onclick = function(){
                console.log(i);
            }
        })(i)
    }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

⚠️​注意:闭包不代表性能高

  • 处理异步函数(设置为内部函数)
// 试图发现下面错误的地方:
let lis = document.querySelector('.nav').querySelectorAll('li');
for (let i = 0;i<lis.lenght;i++){
    setTimeout(function(){ 
	        console.log(lis[i].innerHTML);	
    },3000);
}
// setTimeout属于异步程序,会压入异步执行队列
// 异步程序是当同步队列执行结束后,才执行,故上述程序会报错的。

// 改进: 在原先的异步函数的基础上又外包了一个闭包函数
let lis = document.querySelector('.nav').querySelectorAll('li');
for (let i = 0;i<lis.lenght;i++){
	(function(i){
        setTimeout(function(){
            console.log(lis[i].innerHTML);
        }, 3000)
    })(i);   
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

这里的闭包函数:

(function(i){
    //异步函数执行代码,可以直接读到外部的变量i
    function(){}
})(i)
1
2
3
4
  • 计算打车价格
let car = (function(){
    let start = 13;// 起步价
    let total = 0;// 总价
    return {
        // 正产的总价
        price: function(n){
            if(n<=3){
                total = start;
            }else {
                total = start + (n-3)*5;
            }
            return total;
        },
        // 拥堵之后的费用
        yd: function(flag){
            flag ? total + 10 : total;
        }
    }
})();
console.log(car.price(5));
console.log(car.yd(true));
console.log(car.price(1));
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

这又是一个比较复杂的return的高阶函数,内部函数由对象object输出出来,外部由object调用这个函数。

思考题:

// 思考题1:
let name = "The Window";
let object = {
    name : : "My Object",
    getNameFunc: function(){
        retrurn function(){
            return this.name;
        }
    }
}
console.log(object.getNameFunc()());// 全局变量下的变量"The Window"

// 思考题2:
let name = "The Window";
let object = {
    name : : "My Object",
    getNameFunc: function(){
        let that = this;
        retrurn function(){
            return that.name;
        }
    }
}
console.log(object.getNameFunc()());// 对象内部的变量"My Object"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

解析:object.getNameFunc()()的过程

  • 第一步需要将变量中的函数保存取出:let f = object.getNameFunc()

    相当于函数赋值: f = function(){},此时this的指向为f的内存地址window

  • 第二步运行真实函数:f()

解析2:

  • 当f()运行时,先将this的指向缓存下来,再执行that.name就可以找到对象的属性了。

# 6.浅拷贝与深拷贝

  • 浅拷贝

    // 传统的浅拷贝:由遍历对象实现
    let obj = {
        id: 1,
        name: 'andy',
        msg: {age: 18},
        fn: function() {
            console.log('a');
        }
    };
    
    var o = {};
    for (let k in obj){
        // k是属性名,obj[k]属性值
        o[k] = obj[k];
    }
    console.log(o);//拷贝后的对象
    o.msg.age = 20;
    console.log(obj);//发现原对象被修改了
    
    // 内置写法: 浅拷贝的简单写法
    Object.assign(o, obj)
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
  • 使用迭代函数方式实现深拷贝

    function deepClone(obj){
        let objClone =  Array.isArray(obj) ? [] : {};
        if (obj && typeof obj === 'object') {
            for(let key in obj){
                if (obj[key] && typeof obj[key] === 'object'){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    objClone[key] = obj[key]
                }
            }
        }
        return objClone;
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
编辑 (opens new window)
上次更新: 2022/04/06, 15:04:00
构造函数与原型
函数柯里化

← 构造函数与原型 函数柯里化→

最近更新
01
如何理解浏览器的 user agent 用户代理的含义?
11-05
02
浏览器事件循环机制
10-31
03
浏览器页面渲染机制【2023】
10-15
更多文章>
Theme by Vdoing | Copyright © 2020-2023
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式