JS技巧技法总结——闭包原理、数组展平、前端语音、Proxy 数据绑定和监听、计数器

开发、阅读、学习中接触到、整理的一些知识点。javascript

JS计数器的几种实现

  • 全局变量
let  count = 0;
const  countUp = () =>  count++;
  • 闭包
// javascript

const  countUp = (() => {
    let  count = 0;
    return () => {
        return ++count;
    };
})();
console.log(countUp()); // 1
console.log(countUp()); // 2
  • 函数属性
// javascript
let  countUp = () => {
    return ++countUp.count;
};
countUp.count = 0;
console.log(countUp()); // 1
console.log(countUp()); // 2
  • 函数属性(TS)
interface  Counter {
(): void; // 这里定义Counter这个结构必须包含一个函数,函数的要求是无参数,返回值为void,即无返回值
count: number; // 并且这个结构还必须包含一个名为count、值的类型为number类型的属性
}
const  getCounter = (): Counter  => { // 这里定义一个函数用来返回这个计数器
    const  c = () => { // 定义一个函数,逻辑和前面例子的同样
        c.count++;
    };
    c.count = 0; // 再给这个函数添加一个count属性初始值为0
    return  c; // 最后返回这个函数对象
};

const  counter: Counter = getCounter(); // 经过getCounter函数获得这个计数器
counter();
console.log(counter.count); // 1
counter();
console.log(counter.count); // 2

前端语音

  • 语音播报:在项目中须要对ajax请求返回的消息进行语音播报,str 为返回的data(能够在浏览器控制台尝试哟~)
//语音播报

function  voiceAnnouncements(str){
//百度
    var  url = "http://tts.baidu.com/text2audio?lan=zh&ie=UTF-8&text=" + encodeURI(str); // baidu
    var  n = new  Audio(url);
    n.src = url;
    n.play();
}
voiceAnnouncements('你好,今天吃的什么?')
A tiny JavaScript Speech Recognition library that lets your users control your site with voice commands.
annyang has no dependencies, weighs just 2 KB, and is free to use and modify under the MIT license.

数组展开的N种方法

  • 循环加递归
  • flat
  • flatMap
  • toString后split
  • join后split

使用 Proxy 来实现一个数据绑定和监听

Proxy简介:java

let  p = new  Proxy(target, handler);
// `target` 表明须要添加代理的对象
// `handler` 用来自定义对象中的操做
let  onWatch = (obj, setBind, getLogger) => {
    let  handler = {
        get(target, property, receiver) {
            getLogger(target, property)
            return  Reflect.get(target, property, receiver);
        },

        set(target, property, value, receiver) {
            setBind(value);
            return  Reflect.set(target, property, value);
        }
    };
    return  new  Proxy(obj, handler);
};


let  obj = { a:  1 }
let  value
let  p = onWatch(obj, (v) => {
    value = v
}, (target, property) => {
    console.log(`Get '${property}' = ${target[property]}`);
})
p.a = 2  // bind `value` to `2`
p.a  // -> Get 'a' = 2

再谈闭包

一等公民的定义

  在编程语言中,一等公民能够做为函数参数,能够做为函数返回值,也能够赋值给变量。例如,字符串在几乎全部编程语言中都是一等公民,字符串能够作为函数参数,字符串能够做为函数返回值,字符串也能够赋值给变量。对于各类编程语言来讲,函数就不必定是一等公民了,好比Java 8以前的版本。对于JavaScript来讲,函数能够赋值给变量,也能够做为函数参数,还能够做为函数返回值,所以JavaScript中函数是一等公民。react

动态做用域与静态做用域

  注意,是说做用域,不是类型。
  若是一门语言的做用域是静态做用域,那么符号之间的引用关系可以根据程序代码在编译时就肯定清楚,在运行时不会变。某个函数是在哪声明的,就具备它所在位置的做用域。它可以访问哪些变量,那么就跟这些变量绑定了,在运行时就一直能访问这些变量。即静态做用域能够由程序代码决定,在编译时就能彻底肯定。大多数语言都是静态做用域的。
  动态做用域(Dynamic Scope)。也就是说,变量引用跟变量声明不是在编译时就绑定死了的。在运行时,它是在运行环境中动态地找一个相同名称的变量。在 macOS 或 Linux 中用的 bash 脚本语言,就是动态做用域的。git

闭包

  闭包的内在矛盾是运行时的环境和定义时的做用域之间的矛盾。那么咱们把内部环境中须要的变量,打包交给闭包函数,它就能够随时访问这些变量了。github

  闭包这个概念,对于初学者来说是一个挑战。其实,闭包就是把函数在静态做用域中所访问的变量的生存期拉长,造成一份能够由这个函数单独访问的数据。正由于这些数据只能被闭包函数访问,因此也就具有了对信息进行封装、隐藏内部细节的特性。ajax

闭包与面向对象

  听上去是否是有点儿耳熟?封装,把数据和对数据的操做封在一块儿,这不就是面向对象编程嘛!一个闭包能够看作是一个对象。反过来看,一个对象是否是也能够看作一个闭包呢?对象的属性,也能够看作被方法所独占的环境变量,其生存期也必须保证可以被方法一直正常的访问。编程

闭包的实现

  • 函数要变成 playscript 的一等公民。也就是要能把函数像普通数值同样赋值给变量,能够做为参数传递给其余函数,能够做为函数的返回值。
  • 要让内层函数一直访问它环境中的变量,无论外层函数退出与否。

概括总结

  1. 由于JavaScript是静态做用域的,因此它内部环境中须要的变量在编译时就肯定了,运行时不会改变;
  2. 又由于JavaScript中,函数是一等公民,能够被调用,能够做为参数传递,能够赋值给变量,也能够做为函数返回值,因此它的运行时环境很容易变化;
  3. 当函数做为参数返回时,其外层函数中的变量已经从调用栈弹出,可是咱们必须让内部函数能够访问到它须要的变量,所以运行时的环境和定义时的做用域之间就产生矛盾;
  4. 因此咱们把内部环境中须要的变量,打包交给内层函数(闭包函数),它就能够随时访问这些变量了,就造成了闭包。

本文首发于我的博客,欢迎指正和star。react-native

相关文章
相关标签/搜索