分类
JavaScript 学习笔记

LeetCode 35. 搜索插入位置 JS

比较弱的写法了,用到两个es6方法 includes 和 findIndex

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number}
 */
var searchInsert = function(nums, target) {
    
    
    const xt = (element) => element == target;

    const bxt = (element) => element > target;

    if(nums.includes(target)) {
        return nums.findIndex(xt)
    }

    if(target>nums[nums.length-1]) {
        return nums.length
    }

    return nums.findIndex(bxt)

};
分类
JavaScript 学习笔记

LeetCode 771. 宝石与石头 JavaScript

题解里看到的,用到两个不怎么常用的方法 .filter() 和 ES6 的 .includes()

/**
 * @param {string} J
 * @param {string} S
 * @return {number}
 */
var numJewelsInStones = function(J, S) {
    let jarr = J.split('')
    let sarr = S.split('')
    return sarr.filter(item => jarr.includes(item)).length 
};
分类
JavaScript 学习笔记

LeetCode 1. 两数之和 JS

好弱哈哈~~

/**
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
var twoSum = function(nums, target) {
    var answer = []
    dance:
    for(let i = 0; i < nums.length ; i++) {
        for(let s = i+1; s < nums.length ; s++) {
            if (target - nums[i] === nums[s]) {
                answer.push(i)
                answer.push(s)
                break dance
            }
        }
    }
    return answer
};
分类
JavaScript 使用笔记

1688开放平台获取access_token代码nodejs版本

const https = require('https');
const app = require("./lib/app")

const options = {
    hostname: 'gw.open.1688.com',
    port: 443,
    path: `/openapi/param2/1/system.oauth2/getToken/${app.appKey}?grant_type=refresh_token&client_id=${app.appKey}&client_secret=${app.appSecret}&refresh_token=${app.refresh_token}`,
    method: 'POST'
};

const req = https.request(options, (res) => {
    res.on('data', (d) => {
        process.stdout.write(d);
    });
});

req.on('error', (e) => {
    console.error(e);
});
req.end();
分类
JavaScript 使用笔记

1688开放平台API接口http请求链接生成代码nodejs版本

const crypto = require("crypto")
const app = require("./app")

let gw = 'http://gw.open.1688.com/openapi'

module.exports = (code_arr, apiInfo) => {

    //将token加入参数列表
    code_arr.access_token = app.access_token

    //将第一个签名因子 urlPath 加上 appkey
    apiInfo += app.appKey

    //构造第二个签名因子 排序
    let aliParams = []

    Object.keys(code_arr).forEach((val) => {

        aliParams.push(val + code_arr[val])

    })

    aliParams.sort()

    let sign_str = aliParams.join('')

    // 得出要签名的字符串
    sign_str = apiInfo + sign_str
    //签名
    let code_sign = (crypto.createHmac('sha1', app.appSecret).update(sign_str).digest('hex')).toUpperCase()
    
    //得出url中的参数
    let urlParams = ''

    Object.keys(code_arr).forEach((val) => {
        urlParams += `${val}=${code_arr[val]}&`
    })
    
    // 生成url
    let url = `${gw}/${apiInfo}?${urlParams}_aop_signature=${code_sign}`

    return url

}

code_arr 为入参,apiinfo为要请求的api接口

分类
JavaScript

在 Angular 中使用 Font Awesome 图标库

首先安装 fontawesome,下面使用yarn安装,也可以使用npm

yarn add @fortawesome/fontawesome-svg-core \
  yarn add @fortawesome/free-solid-svg-icons \
  yarn add @fortawesome/angular-fontawesome

然后编辑 app.module.ts 文件,引入 FontAwesomeModule

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { FontAwesomeModule } from '@fortawesome/angular-fontawesome';
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FontAwesomeModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

接着在 app.component.ts 文件中,引入我们要使用的图标

import { Component } from '@angular/core';
import { faCoffee } from '@fortawesome/free-solid-svg-icons';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app';
  faCoffee = faCoffee;
}

上面的例子引入了 coffee 图标,然后就可以在模板中使用

<div style="text-align:center">
  <fa-icon [icon]="faCoffee"></fa-icon>
</div>

说明

其实我很不喜欢fontawesome 5+,因为它把图标分成了好几类,我们刚才只安装了 free-solid-svg-icons ,所以像 github 等图标我们无法使用,需要安装 free-brands-svg-icons 库才能使用。

具体说明参见fontawesome官方说明。

参考

分类
JavaScript

[简记]JS生成指定位数的随机数

以下函数通过将生成“指定位数”个0-9的随机数拼接起来达到目的

function randomNum(n){
  var t='';
  for(var i=0;i<n;i++){
    t+=Math.floor(Math.random()*10);
  }
  return t;
}
分类
JavaScript

JavaScript与Java中的默认参数

默认参数(也称为可选参数)是提供给函数的参数的默认值。如果用户不提供此参数的值,则将使用默认值。如果用户提供了默认参数的值,则将使用用户提供的值而不是默认值。、

在JavaScript中,所有的函数参数都是可选的,默认情况下是未定义的。来看下面一个例子:

function add(a, b) {
  return a + b;
}
// 因为所有参数默认为未定义
// 直接调用add()相当于调用add(undefined,undefined)
// 强行对undefined 进行运算会返回NaN
add(); // -> NaN
// b 未定义
// 调用add(1)等于调用add(1, undefined),同样返回NaN
add(1); // -> NaN
add(1, 2); // -> 3

想要让一些参数变得可选可以为他们添加默认值

在JavaScript中,你可以直接这样定义

function add(a, b = 0) {
  return a + b;
}
// 当你没有给出参数b的值时,b将为0
add(1) // 1 + 0 = 1
add(1, 2) // 1 + 2 = 3

想要了解更多关于JavaScript中默认参数的内容可以访问MDN

而在Java中,所有函数参数都是必需的。这意味着由于所有参数都是必需的,所以没有办法给参数设置默认值。

package com.company;
public class Main {
    private static int add(int a, int b) {
        return a + b;
    }
    public static void main(String[] args) {
        // 尝试使用无参数或一个参数调用add
        // 由于所有参数都是必需的,因此会给出编译时错误
        add(); // 编译错误
        add(1); // 编译错误
    }
}

尽管在Java中存在这种限制,但是我们利用Java的重载机制对代码进行变通,可以做到如JavaScript中的类似效果,如下所示

重载方法:如果一个类中的方法具有不同的参数列表,那么类中的方法可以具有相同的名称。

package com.company;
public class Main {
    private static int add(int a, int b) {
        return a + b;
    }
    private static int add(int a) {
        return add(a, 0);
    }
    private static int add() {
        return add(0, 0);
    }
    public static void main(String[] args) {
        add(); // -> 0
        add(1); // -> 1
        add(1, 2); // -> 3
    }
}

了解更多关于Java中重载方法的知识可以访问Defining Methods (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

翻译

根据原文Default parameters in JavaScript and Java – Tănase Hagi – Medium,略有修改

分类
JavaScript

JavaScript Memoization缓存技术

Memoization是一种用来优化计算程序使之更快的技术,通过储存调用函数的结果并在传进同样参数的时候直接返回其返回值来实现。
而通常,我们只在递归函数中才需要反复调用一个已经执行过的函数的返回值。所以这里以一个最基本的计算阶乘的递归函数为例,如下所示

let times = 0;
function factorial(n) {
  if (n === 0 || n === 1) return 1;
  if (n === 2) return 2;
  console.log(`calculating ${++times} times`)
  return n * factorial(n - 1);
}
factorial(10)
factorial(10)
factorial(10)
factorial(10)

我们执行了四次factorial()函数,并且都是传递了同一参数,但是计算机照样还是会从头执行一遍,这样就造成了资源浪费。
所以我们可以想到,如果我们可以把每次计算的结果缓存到内存里,如果参数没有改变,那就直接返回这个缓存的结果就好了。这是一种以空间换时间的优化方式。
接着再看一个简单的例子

const double = n => n * 2;
const memoize = (fn) => {
  const cache = {}; // 创建一个缓存对象
  return (n) => {
    if (n in cache) {
      console.log('在缓存中');
      return cache[n];
    }
    console.log('从头运算');
    const result = fn(n);
    cache[n] = result; // 将其存储在缓存中
    return result;
  }
}
const memoizedDouble = memoize(double);
memoizedDouble(4) // 从头运算
memoizedDouble(4) // 在缓存中
memoizedDouble(5) // 从头运算
memoizedDouble(5) // 在缓存中
memoizedDouble(4) // 在缓存中

这也是所谓JavaScript闭包的典型运用,上面的memoize()函数实际上是实现了一个 size 无限大的缓存,只要不同的参数,运算过一次以后,都会存入缓存中。
但是我们传入一个递归函数进去是无法实现目的的,这个时候应该确保递归时,也应调用这个记忆后的函数。

// same memoize function
const memoize = (fn) => {
  const cache = {}; // 创建一个缓存对象
  return (n) => {
    if (n in cache) {
      console.log('在缓存中');
      return cache[n];
    }
    console.log('从头运算');
    const result = fn(n);
    cache[n] = result; // 将其存储在缓存中
    return result;
  }
}
const factorial = memoize(
  (n) => {
    if (n === 0) return 1;
    return n * factorial(n - 1);
  }
)
factorial(10) // 从头运算
factorial(10) // 在缓存中

可以发现实际上缓存中实际上保存从 1 到 10 所有的阶乘结果。
缓存这种存储某些数据以给将来的使用这一概念,实际上运用的方向非常多,比如HTTP缓存,而Memoization基本上就是这种特定的,缓存函数返回值的技术。

在哪些地方运用

通常我们并不会在所有的地方都使用这种空间换时间的优化技术,一般来说有下面几个规律:

  • 函数首先必须是一个 pure function,每次对于相同的输入,都应该有相同的返回。

  • 因为是为了以空间交换时间,因此函数必须有着有限的输入范围,来让缓存的值可以呗被频繁的多次使用。

  • 最合适的使用时机,应该是针对需要大量计算的 heavy computational function, 可以极大的提高性能。

如果对React相关生态的比较熟悉的话,就知道有一个 Reselect 的工具库,来帮助优化从state树提取数据映射到相关组件这一过程。它的源码也非常短小精悍,值得一读。

分类
JavaScript

使用Node.js开发一个静态博客生成器(三)——代码高亮

实现代码很简单,我们知道有highlight.js可以直接在浏览器中给pre标签中的代码加入高亮标签的样式,然后引入对于的高亮样式CSS文件即可,我们可以在使用任何程序的网站中使用这个库。
但是highlight.js经过压缩后还是有几十kb,同样,在浏览器中渲染HTML标签也会耗时耗资源,所以干脆在服务端(生成页面的时候)就给代码加上高亮样式,我这里举两个例子,分别是两个Markdown生成器的使用方法:

MarkdownIt

这是我现在在用的解析器,在生成md实例的时候可以直接启用highlight.js插件。

const MarkdownIt = require('markdown-it');
const hljs = require('highlight.js');
const md = new MarkdownIt({
  highlight: function(str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return '<pre><code class="hljs ' + lang + '">' +
          hljs.highlight(lang, str, true).value +
          '</code></pre>';
      } catch (__) {}
    }
    return '<pre><code>' + md.utils.escapeHtml(str) + '</code></pre>';
  }
});

然后使用md.render()方法解析MD时就会自动加上hljs的高亮样式了。

marked

这是另一款非常受欢迎的markdown解析器,我曾经也尝试使用过,相比markdownit,我认为它配置起来更加简单,同样,它也可以直接启用highlight.js拓展

const marked = require('marked');
const hljs = require('highlight.js');
marked.setOptions({
  highlight: (code) => hljs.highlightAuto(code).value,
})
marked(markdown)