开发、阅读、学习中接触到、整理的一些知识点。
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
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
//语音播报 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.
Proxy简介:
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中函数是一等公民。
注意,是说作用域,不是类型。
如果一门语言的作用域是静态作用域,那么符号之间的引用关系能够根据程序代码在编译时就确定清楚,在运行时不会变。某个函数是在哪声明的,就具有它所在位置的作用域。它能够访问哪些变量,那么就跟这些变量绑定了,在运行时就一直能访问这些变量。即静态作用域可以由程序代码决定,在编译时就能完全确定。大多数语言都是静态作用域的。
动态作用域(Dynamic Scope)。也就是说,变量引用跟变量声明不是在编译时就绑定死了的。在运行时,它是在运行环境中动态地找一个相同名称的变量。在 macOS 或 Linux 中用的 bash 脚本语言,就是动态作用域的。
闭包的内在矛盾是运行时的环境和定义时的作用域之间的矛盾。那么我们把内部环境中需要的变量,打包交给闭包函数,它就可以随时访问这些变量了。
闭包这个概念,对于初学者来讲是一个挑战。其实,闭包就是把函数在静态作用域中所访问的变量的生存期拉长,形成一份可以由这个函数单独访问的数据。正因为这些数据只能被闭包函数访问,所以也就具备了对信息进行封装、隐藏内部细节的特性。
听上去是不是有点儿耳熟?封装,把数据和对数据的操作封在一起,这不就是面向对象编程嘛!一个闭包可以看做是一个对象。反过来看,一个对象是不是也可以看做一个闭包呢?对象的属性,也可以看做被方法所独占的环境变量,其生存期也必须保证能够被方法一直正常的访问。
本文首发于个人博客,欢迎指正和star。