Giter VIP home page Giter VIP logo

til's Issues

reduce: 实现一个reduce方法

今天无意间看到一个面试题有问到如何实现一个reduce函数,额,花了点时间算是写下来了。写这个方法的前提是了解这个api。

  • 默认初始值
    这个就是对应的reduce的第二个参数。
    • 如果有这个参数,那么这个参数将作为reduce的第一个参数(函数)的第一个参数,(函数)的第二个参数是数组的第一个参数;
    • 如果没有这个,那么reduce函数的第一个参数(函数)的第一个参数是数组的第一个元素,(函数)的第二个参数就是数组的第二个元素。

所以,reduce函数的第一个参数(函数)的第三个参数(索引), 就是根据reduce函数的第二个参数在数组中的牵引做的判断。

好了,我们知道了这个reduce函数的api之后,我们尝试来写个:

const array = [11, 22, 33]
const reducer = (arr, fn, initValue) => {
  if(!Array.isArray(arr)) throw new Error('First Argument Must Be Array')
  if(typeof fn !== 'function') throw new Error('Second Argument Must Be Function');
  
  var i = initValue ? 0 : 1 // 因为如果不存在initValue, 数组第一个就得补上,所以索引从1开始。和下面的赋值操作的顺序不可以对调!
  initValue = initValue ? initValue : arr[0] //因为存在init的话,第一个就是init, 不存在,第一个就是数组的第一个元素
  for(i; i < arr.length; i++){
    initValue = fn(initValue, arr[i], i, arr)
  }
  
  return initValue
} 
reducer(array, (sum, i) => sum + i)

you dont known js - trick && skill

这里记录一些you don't know js提出的一些小细节,小技巧。

章: types&&grammer 点击查看此章各小节

values

  • isNaN
    测试传入的东西要么不是number,要么是number。但是这样是严谨的吗?
var a = 2 / "foo";
var b = "foo";

a; // NaN
b; // "foo"

window.isNaN( a ); // true
window.isNaN( b ); // true -- ouch!

"foo"实际上不是一个number,但它绝对不是NaN值!
显然,这是不合理的,foo并不是一个NaN。所以es6添加了Number.isNaN, 就是对这个问题(bug)的补充。

if (!Number.isNaN) {
	Number.isNaN = function(n) {
		return (
			typeof n === "number" &&
			window.isNaN( n )
		);
	};
}

var a = 2 / "foo";
var b = "foo";

Number.isNaN( a ); // true
Number.isNaN( b ); // false -- phew!

可以发现,首先确认他是不是数字类型,然后再进行isNaN判断。

Coercion, 点击查看详细内容

  • ~
const arr = ['ni', 'wo', 'ta']
//使用~之前
if(arr.indexOf('js') === -1){
  //不存在
}
//使用~之后
if(!~arr.indexOf('js')){
  //不存在
}

记住: ~操作符类似于-(x + 1)

grammer 点击查看详细内容

  • ||&&优先级

先自己问自己一把,||&&的哪个优先级更高?
在很长一段时间里,我认为这两个优先级是一样的,实则不然。
看下面代码:

false && true || true // ??
(false && true) || true // ??

通过上面的例子,我想你可以知道优先级高低的答案了。
当然,你可以参考MDN - Operator Precedence

考虑下面这个例子会输出什么?

var a = 42;
var b = "foo";
var c = false;

var d = a && b || c ? c || b ? a : c && b : a;

d;		// ??

上面例子具体的可以看这里 运算符优先级问题

章:scope&&closures 点击查看各小节

what is scope 点击查看详细内容

ReferenceErrorTypeError区别

  • ReferenceError
    这个是作用域解析失败相关而抛出的异常

  • TypeError
    作用域解析成功,但试图对结果执行非法/不可能的操作。

lexical scope 点击查看详细内容

  • eval

    他会修改现有的词法作用域(非严格模式)

     function run(str){
         eval(str)
          console.log(yourName)
     }
     run("var yourName = 'xhs'")

    然后你可以在里面试试严格模式。

  • with
    创建一个 全新的词法作用域

    function foo(obj) {
    	with (obj) {
    		a = 2;
    	}
    }
    
    var o1 = {
    	a: 3
    };
    
    var o2 = {
    	b: 3
    };
    
    foo( o1 );
    console.log( o1.a ); // 2
    
    foo( o2 );
    console.log( o2.a ); // undefined
    console.log( a ); // 2 -- Oops, leaked global!

    可以看见,LHS查找不存在,就直接到了上一层。

章:this&object prototypes 点击查看此章各小节

this指向, 点击查看详细内容

  • 默认绑定 🛫
  • 隐式绑定 🛩
  • 显示绑定🛩
  • new绑定🛩
    绑定关系是按照上面依次增强 🛩

Objects 点击查看详细内容

  • property
    对于熟悉描述,在之前有做过小小的对象属性总结
    这里说下enumerable 是啥:就是在迭代(循环遍历)中包含。
    可以检查是否为enumerable,在对象属性总结那里有提到,现在来说下另外一个方法propertyIsEnumerable
var myObject = { };

Object.defineProperty(
	myObject,
	"a",
	{ enumerable: false, value: 2 }
);
myObject.propertyIsEnumerable( "a" ); // false

propertyIsEnumerable(..)测试给定的属性名称是否 直接 存在于对象上,并且也是enumerable:true

Prototypes 点击查看详细内容

a instanceof Foo; // true
  • instanceof的意思:a的整个[[Prototype]]链中,Foo.prototype任意指向的对象有没有出现?
Foo.prototype.isPrototypeOf( a ); // true
  • isPrototypeOf(..)的意思是: a整个[[Prototype]]链中,Foo.prototype有没有出现?

isPrototypeOf的实现如下:

function isRelatedTo(o1, o2) {
	function F(){}
	F.prototype = o2;
	return o1 instanceof F;
}

var a = {};
var b = Object.create( a );

isRelatedTo( b, a ); // true

柯里化函数

之前有写过一篇文章,是说柯里化函数和函数组合, 看完之后真是大受脾益,尤其是在看redux源码的时候,就感觉很顺通。

今天上午看了下简书,发现了一个被面试到的问题,思考了下。问题是这样的:

函数闭包与柯里化(让手写一个函数完成求和操作,func(1)(2)(3)、func(1,2)(3)和func(1,2,3)都能保证可以正常求和)

function add(...args) {
  return args.reduce((total, item) => total = total + item, 0)
}

function func(fn){
  return (length) => (...args) => (length - args.length) ? func(fn)(length).bind(null, ...args) : fn(...args)
}
add3 = func(add)(3)
add3(1)(2)(3)
add3(1,2)(3)
add3(1,2,3)

上面的func看起来有些怪怪的, 有这个func(fn)(length),那么我们来改下下

function func(fn){
  return (length) => varFun =  (...args) => (length - args.length) ? varFun.bind(null, ...args) : fn(...args)
}

没事写了个双向绑定(defineProperty&&Proxy)

<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>测试</title>
</head>
<body>
  Name: <input class='input' name='input'/>
  add: <button class='button'>+</button>
</body>
<script>
let input = document.querySelector('.input')
let button = document.querySelector('.button')
let num = 0

button.addEventListener('click', function(){
  num++
  input.value = num
})

let proxy = new Proxy(input, {
  set(trapTarget, key, value, receiver) {
    if (isNaN(value)) {
      throw new TypeError("Property must be a number.");
    }

    return Reflect.set(trapTarget, key, value, receiver);
  }
})

Object.defineProperty(input, 'value', {
  enumerable: true,
  value: '',
  get: function () {
    console.log('get this value is', this._value)
    return this._value
  },
  set: function (val) {
    console.log('set this value is', val)
    this._value = val
  }
})


</script>
</html>

惰性函数

今天看到一篇文章中有提到 惰性函数 。感觉很新奇,去查了下,发现就是自己调用自己。

可以让你只在第一次的时候调用你需要处理的函数,后面可以直接使用函数。

var foo = function() {
  console.log('你会发现我只出现一次哦,不管你调用几次')
  foo = function() {
    console.log('嘻嘻,我出现了哦')
  }
  foo()
}

foo() // 你会发现我只出现一次哦, 不管你调用几次; 嘻嘻,我出现了哦
foo() //嘻嘻,我出现了哦

还挺有意思的,留下个问题,你觉得这个是因为啥,为啥会出现上面的情况?

js到底是解释型语言还是编译型语言?

之前一直没有怎么考虑过这个问题,只是貌似听说过js是一个解释型语言,不需要编译。
为什么突然扯到这个类型上面呢,主要是因为在群里看到争论,于是搜索了下。

看到一篇帖子,说Is Javascript a compiled language?, 他重复说了很多次, 以及确定js就是编译型语言,很遗憾的是,下面的评论打脸了,很确定的告诉他,js不是一个编译型语言,编译的子集并不能说明语言本身是一个编译型的语言。

然后我们在quora里也可以看到说js是一个解释型语言.

这里面有两个回答不错,其中有段话很直接:

Bottom Line :

Javascript is interpreted. As in the language has been implemented in that fashion as because it was >supposed to be used on the browser platform. And since interpreted language is not a spec, browser >vendors have modified it for performance.
很直接的说明了,由于解释型语言不是规范,所以浏览器供应商便更改了他的性能。

我们再来看看stack exchange的一个问答,Is JavaScript interpreted by design?

The semantics of statements and expressions in the language are defined in terms of completion >specification which are trivially implemented in an interpreter, but the specification does not require >that.

意思就是 语言中语句和表达式的语义是根据完成规范定义的,这些规范在解释器中通常可以实现,但规范并不要求这样。

并且在语言定义的时候也没有出现解释器的说明, EcmaScript语言极客们通常使用术语“ES解释器”来指代EcmaScript的实现,但规范不使用该术语。语言概述特别描述了与解释器无关的术语:

ECMAScript is object-based: basic language and host facilities are provided by objects, and an ECMAScript program is a cluster of communicating objects.
可以发现,并没有解释器这个词眼出现。

另外可以参考下ECMAScript engines, 有对应的编译器和解释器,这都是实现规范的一种方法,所以你不需要这些也可以,只是有实现的差异化。

所以说,js不是编译型语言,他是解释型的语言。但是也看情况,就语言本身而言,不存在情况。
他本身就是一个解释型的语言,以至于解释器也不需要。

bind, 函数的第二个参数会输出什么?

今天看到一个地方有误解,自己试了下,感觉挺不错。

你觉得下面的这个consolesaga会输出什么?

function run({name, age}, saga, ...options){
  console.log('name is', name, 'saga is', saga)
}
let boundRun = run.bind(null, {name: 'xiaohesong', age: 18})

function *rootSaga() {
  yield 'i am a generator function'
}

boundRun(rootSaga)

[每日见闻-2017-07-27]Rails细节的性能对比

  • method argument
def hello(foo: nil, bar: nil)
end
10_000.times { hello(foo: 1, bar: 2) }

# Runtime => 10.354 ms
def hello(options = {})
  foo, bar = options[:foo], options[:bar]
end
10_000.times { hello(foo: 1, bar: 2) }
# Runtime => 5.064 ms
  • obj.method VS obj attr_reader
class Foo
  def initialize(val)
    @val = val
  end

  def val
    @val
  end
end

object = Foo.new("bar")
100_000.times { object.val }
# Runtime => 9.284 ms
class Foo
  def initialize(val)
    @val = val
  end

  attr_reader :val
end

object = Foo.new("bar")
100_000.times { object.val }
# Runtime => 6.966 ms

js的map和forEach到底哪个速度快?

今天看到一篇文章,一个大神写的。可以看Speed Considerations这个地方,他说他那里测试是mapforEach快不少。

image

我觉得不太可能,毕竟map是返回一个新的数组呀。

//example.js
mapTag = "Map Spent Time is"
eachTag = "Each Spend Time is"
mapArr = eachArr = [...Array(1000000)]

console.time(mapTag)
mapArr.map((i, index) => {
  return index * 2
})
console.timeEnd(mapTag)

console.time(eachTag)
eachArr.forEach((i, index) => {
  return eachArr[index] = index * 2
})
console.timeEnd(eachTag)

从上面这个例子可以发现不是这样的。

不对呀,jsperf应该不会出问题的。难道是forEach有提升吗?找了下,没有找到相关的资料,值看到了说17年八月初forEach有提升十倍,那也不对呀,上面的文章提到的是2017年12月份。

jsperf的工作方式

比较好奇啊,这是为啥呐。

[每日见闻-2017-08-29]es6

  • module
    module.exports的作用等同于export default
module.exports = {
  foo: 'hello'
};

// 等同于
export default {
  foo: 'hello'
};

[每日见闻-2017-06-30]使用Rails构建Api.

Rails的框架太重,很多人以Api为主的项目,都会选择其他的框架.sinatra,rabl,grape..诸如此类的框架.
其实用Rails也还是可以的.直接controller继承自ActionControll::Metal.仅仅加载用到的模块的模块.
参考这里

一些不错的js题

输出内容系列

输出什么?

function getPersonInfo(one, two, three) {
  console.log(one);
  console.log(two);
  console.log(three);
}

const person = "Lydia";
const age = 21;

getPersonInfo`${person} is ${age} years old`;

是不是大吃一惊,哈哈。这个细节还真是没有注意到。

[每日见闻-2017-07-20]关于self的小细节

  • self在当前的initialize中直指当前的实例对象
class Foo
  def initialize(x)
    self.c x
  end
 
  def c(x)
    puts "c的参数是#{x}"
  end
end
f = Foo.new(1)
  • 带给我的感觉
    self在很大程度上类似.都是指定当前的实例.给我的感觉就是
self == @
!self.eql?(@)

类似于coffee js

this && @

例如:

class Foo
  attr_accessor :name
  def initialize(x)
    @name = "wo"
  end
end

class Foo
  attr_accessor :name
  def initialize(x)
    self.name = "wo"
  end
end

f = Foo.new(3)
puts f.name

再比如

class A
  @num = 8
  def show
    puts @num
  end
end

class B < A
  def initialize
    @num = 3
  end
end

b = B.new
b.show

[每日见闻-2017-07-03]Rails flash,Middleware和Metal的区别, 重构Routes的方法

Rails flash

  • Rails的消息提示有notice, alert,其实还可以追加类型.
class ApplicationController < ActionController::Base
  add_flash_types :warning, :success, :danger
end
  • notice的区别
# 1. 新建失败时,可以
 render 'new', flash.now[:notice] = '嘻嘻嘻' 
# 2. 新建成功时,可以
redirect_to xx_path, flash['notice']= '嘻嘻嘻'

Middleware Metal的区别

Middleware 是 Action Dispatch 实现的,而 Metal 是 Action Controller 实现的。
Middleware 是在请求进入 action 之前,而 Metal 是在请求进入 action 之后。
Middleware 需要的环境是 env,作用的是 app;而 Metal 增强组件需要的环境是 Controller & action,目的主要是对请求做处理,并响应。

重构路由

-. 首先得知道路由里 scopenamespace的区别.之前倒是使用namespace比较多,对于scope知之甚少.

scope as: 'admin', path: '/admin', module: 'admin' do
  #some resources
end

# 等价于

namespace :admin do
  # some resources
end

-. 重构路由
有些项目是api和页面共存的. 大量充斥着重复的代码.

# 重构前
namespace :a do
  resources :users
  resources :orders
end

namespace :b do
  resources :users
  resources :orders
end

# 重构后
concern :base do
  resources :users
  resources :orders
end

namespace :a do
  concerns :base
end

namespace :b do
  concerns :base
end

来看看D大神的说法

[每日见闻-2017-07-26]-ssh相关-配置远程服务器别名

别名服务器

cd ~/.ssh
# vim config
Host nickname #你的别名
User user #你的远程用户
HostName 192.168.2.2 #你的远程ip
Port 22 #你的远程端口号
ForwardAgent yes
ServerAliveInterval 60 #断开时间

再运行之前,还需要把ssh添加到远程服务器

ssh-keygen #如果没有 ssh
ssh-copy-id user@ip

然后就可以别名登录远程服务器了.

ssh nickname

禁止root登录ssh

# sudo vim /etc/ssh/ssh-config
Port 12345 #可以设置你想要的端口
PermitRootLogin no # 禁止root登录

[每日见闻-2017-08-09]ss配置系列

客户端配置

ubuntu

  1. 安装相关包
sudo apt-get install python-pip
sudo pip install shadowsocks
# sudo vim /ss-conf.json
{
  "server":"remote ip",
  "server_port":你的端口,
  "local_address":"127.0.0.1",
  "local_port":1080,
  "password":"password",    
  "timeout":600,
  "method":"aes-256-cfb"
}

可以通过sslocal -c /ss-conf.json来启动。

每次这样启动比较麻烦,加入开机自动启动.

  • 添加自动动脚本
# sudo vim /home/shadowsock.sh
#!/bin/bash
sslocal -c /ss-conf.json
  • 加入自启动
# sudo vim /etc/rc.local
nohup bash /home/shadowsock.sh > /home/ss-log.txt &
# 上面这个加在`exit 0`之前
sudo cp /usr/local/bin/sslocal /bin/
sudo reboot

服务端配置

ubuntu

  1. 安装相关的包
sudo apt-get update
sudo apt-get install python-pip
sudo pip install shadowsocks

不出意外,会安装成功了这里.然后添加一个配置文件
sudo vim shadowsocks-conf.json:

{
  "server":"0.0.0.0",
  "server_port":8888,
  "local_address":"127.0.0.1",
  "local_port":1080,
  "password":"这里是你的链接ss的密码",    
  "timeout":600,
  "method":"aes-256-cfb"
}

上面就是对应的配置文件,服务端配置好之后,启动shadowsocks:

sudo ssserver -c shadowsocks-conf.json -d start

[每日见闻-2017-08-02]sql整理

关于join

  • Left join
select count(distinct store_name) from scores left join stores on scores.scoreable_id = stores.id and scores.scoreable_type = 'Store' where store.status = 0 and scores.user_type=0;
# 这个是查询 所有带有评分的门店,并且门店是营业状态(0)和评分的类型是用户评分(0)
  • Right join
    left join差不多.不过这个是以右表全表为基础进行处理.

  • inner join
    rubyjoins.sql查询中也可以直接使用join,就是inner join

User.joins(:roles).to_sql
# => "SELECT `users`.* FROM `users` INNER JOIN `users_roles` ON `users_roles`.`user_id` = `users`.`id` INNER JOIN `roles` ON `roles`.`id` = `users_roles`.`role_id`"

Inner join 是左右表等价的.

  • includes
A.includes(:bs).where(bs: {name: '#'}).count
# =>
# SELECT COUNT(DISTINCT `bs`.`id`) FROM `as` LEFT OUTER JOIN `bs` ON `bs`.`a_id` = `as`.`id` WHERE `bs`.`name` = '#'

从上面可以发现,left joinincludesleft outer join很像.其实left joinleft outer join类似于joininner join类似的.此处查看

小方法

  • sum
SUM(CASE WHEN num > 0 THEN 1 else 0 END) AS available_times
  • round
ROUND('123.654',2)
# 123.654 取小数后两位
  • GROUP_CONCAT/CONCAT
    返回拼接的字符串. GROUP_CONCAT与group by使用,效果更佳.

你也是17年才接触前端的吗

感谢库主的分享,仓库内容挺细致的。
不过我有个问题,看你这个仓库貌似是建于17年中下旬。难道你学前端两年不到吗?

js如何翻转一个字符串&&js如何清除数组

翻转字符串

How to reverse a string in JavaScript

const str = "hello"
str.split('').reverse().join('')
//"olleh"
const str = "hello"
[...str].reduce((prev,next)=>next+prev)
//"olleh"
function reverseString(str){
  const arr = [...str]
  let reverse= "";
  while(arr.length){
     reverse = reverse + arr.pop()
  }
  return reverse
}

清空数组

How to clear an array in javascript

var arr = [1,2,3,4,5,6] 
arr = [ ]
console.log(arr)
//empty array [ ] 
var arr = [1,2,3,4,5,6]
arr.length = 0
console.log(arr)
//empty array [ ]
var arr = [1,2,3,4,5,6]
while(arr.length){
   arr.pop()
}
console.log(arr)
//empty array [ ]

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.