JavaScript学习笔记(二十四)函数(四)尾调用优化
外部函数的返回值是一个内部函数的返回值。
尾调用优化的条件
尾调用优化的条件就是确定外部栈帧真的没有必要存在了。
代码在严格模式下执行;
外部函数的返回值是对尾调用函数的调用;
尾调用函数返回后不需要执行额外的逻辑;
尾调用函数不是引用外部函数作用域中自由变量的闭包
下面展示了几个违反上述条件的函数,因此都不符合尾调用优化的要求:
1234567891011121314151617181920"use strict"; // 无优化:尾调用没有返回 function outerFunction() { innerFunction(); } // 无优化:尾调用没有直接返回function outerFunction() { let innerFunctionResult = innerFunction(); return innerFunctionResult; } // 无优化:尾调用返回后必须转型为字符串function outerFunction() { return ...
575. 分糖果
题目给定一个偶数长度的数组,其中不同的数字代表着不同种类的糖果,每一个数字代表一个糖果。你需要把这些糖果平均分给一个弟弟和一个妹妹。返回妹妹可以获得的最大糖果的种类数。链接:https://leetcode-cn.com/problems/distribute-candies
解题思路和代码假设糖果总共m个,种类有n种:当n < m/2时,结果为n;当n > m/2时,结果为m/2;
使用哈希表统计糖果种类数;
使用Set集合直接计算;
代码一:执行用时:128ms;内存消耗:51.4MB;
12345678910111213141516/** * @param {number[]} candyType * @return {number} */var distributeCandies = function(candyType) { let dic = new Map(); let len = candyType.length; for(const i of candyType){ ...
JS 基础技能 1
JavaScript——判断字符串中是否包含某个字符/字符串
方法一:indexOf()
返回某个指定的字符串值在字符串中首次出现的位置;如果不存在,则返回-1;
1234567let str = 'Hello World!';if(str.indexOf("World")){ console.log(true);}else{ console.log(false);}//true
方法二:search()
方法用于检索字符串中指定的子字符串,或检索与正则表达式相匹配的子字符串。如果没有找到任何匹配的子串,则返回 -1。
1234567let str = 'Hello World!';if(str.search("World")){ console.log(true);}else{ console.log(false);}//true
方法三: match()
方法可在字符串内检索指定的值,或找 ...
500.键盘行
题目给你一个字符串数组 words ,只返回可以使用在 美式键盘 同一行的字母打印出来的单词。键盘如下图所示。
美式键盘中:
第一行由字符 “qwertyuiop” 组成。第二行由字符 “asdfghjkl” 组成。第三行由字符 “zxcvbnm” 组成。
提示:
1 <= words.length <= 20
1 <= words[i].length <= 100
words[i] 由英文字母(小写和大写字母)组成
解题思路和代码
创建三个字符串分别表示三行字符;
判断字符串是否符合条件之前先对字符串进行大小写转换;
对单个字符串进行遍历,遍历第一个字符给整个字符串添加标识;
接下来的每次遍历查看是否都属于该标识所代表的字母,如果是继续遍历直至遍历完,反之将标识置为-1,然后跳过整个遍历过程。
将标识不为-1的字符串保存在字符串中并返回。
代码1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556/** ...
JavaScript学习笔记(二十三)函数(三)
函数属性与方法
每个函数都有两个属性:length和prototype。
length 属性保存函数定义的命名参数的个数。
123456789101112function sayName(name) { console.log(name); } function sum(num1, num2) { return num1 + num2; } function sayHi() { console.log("hi"); } console.log(sayName.length); // 1 console.log(sum.length); // 2 console.log(sayHi.length); // 0
prototype是保存引用类型所有实例方法的地方,这意味着toString()、valueOf ()等方法实际上都保存在prototype. 上,进而由所有实例共享。
prototype属性是不可枚举的。
函数还有两个方法: apply()和call(),这两个方法都会 ...
JavaScript学习笔记(二十二)函数(二)
函数声明与函数表达式
JavaScript引擎在任何代码执行之前,会先读取函数声明,并在执行上下文中生成函数定义。
函数表达式必须等到代码执行到它那一行,才会在执行上下文中生成函数定义。
函数声明提升:函数声明会在任何代码执行之前先被读取并添加到执行上下文。
在执行代码时,JavaScript引擎会先执行一遍扫描,把发现的函数声明提升到源代码树的顶部。
如果把代码中的函数声明改为等价的函数表达式,那么执行的时候就会出错
12345678910// 没问题 console.log(sum(10, 10)); function sum(num1, num2) { return num1 + num2; } // 会出错console.log(sum(10, 10)); let sum = function(num1, num2) { return num1 + num2; };
以上代码出错的原因在于并没有执行到let定义函数那一行,并不是因为使用let造成的。
函数作为值
函数名在ECMAScript中就是变量。这意味着不仅 ...
JavaScript学习笔记(二十一)函数(一)
函数名
函数名是指向函数的指针,它们跟其他包含对象指针的变量具有相同的行为。
一个函数可以有多个名称。
ES6所有函数对象都会暴露一个只读的name属性。
包含关于函数的信息;
多数情况下,这个属性中保存的就是一个函数标识符,或者说是一个字符串化的变量名;
函数没有名称会如实显示成空字符串;
使用Function构造函数创建的,则会标识成“anonymous”。
12345678function foo() {} let bar = function() {}; let baz = () => {}; console.log(foo.name); // foo console.log(bar.name); // bar console.log(baz.name); // baz console.log((() => {}).name); //(空字符串)console.log((new Function()).name); // anonymous
如果函数是一个 获取函数、设置函数, ...
JavaScript学习笔记(二十)箭头函数
很大程度上,箭头函数实例化的函数对象与正式的函数表达式创建的函数对象行为是相同的。
箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
12345678let arrowSum = (a, b) => { return a + b; }; let functionExpressionSum = function(a, b) { return a + b; }; console.log(arrowSum(5, 8)); // 13 console.log(functionExpressionSum(5, 8)); // 13
箭头函数简洁的语法非常适合嵌入函数的场景:
123let ints = [1, 2, 3]; console.log(ints.map(function(i) { return i + 1; })); // [2, 3, 4] console.log(ints.map((i) => { return i + 1 })); // ...
JavaScript学习笔记(十九)代理捕获器与反射方法
get()
get()捕获器会在获取属性值的操作中被调用。
对应的反射API方法为Reflect.get()。
275
JavaScript学习笔记(十八)代理基础
代理类似C++指针,因为它可以用作目标对象的替身,但又完全独立于目标对象;
目标对象既可以直接被操作,也可以通过代理来操作。
默认情况下,在代理对象上执行的所有操作都会无障碍地传播到目标对象。
在任何可以使用目标对象的地方,都可以通过同样的方式来使用与之关联的代理对象
直接操作会绕过代理施予的行为。
空代理
除了作为一个抽象的目标对象,什么也不做
代理是使用Proxy构造函数创建的,构造函数接收两个参数:目标对象和处理程序对象。
缺少其中任何一个参数都会抛出TypeError;
创建空代理,可以传一个简单的对象字面量作为处理程序对象。
1234567891011121314151617181920212223242526272829const target = { id: 'target' }; const handler = {}; const proxy = new Proxy(target, handler); // id 属性会访问同一个值console.log(target.id); // target ...