SegmentFault Ruchee的编码人生最新的文章
2016-08-19T17:34:00+08:00
https://segmentfault.com/feeds/blogs
https://creativecommons.org/licenses/by-nc-nd/4.0/
Ruby继承链
https://segmentfault.com/a/1190000006659683
2016-08-19T17:34:00+08:00
2016-08-19T17:34:00+08:00
Ruchee
https://segmentfault.com/u/ruchee
0
<pre><code class="ruby">module M1
end
module M2
end
module M3
end
module M4
end
class Hello
include M1
include M2
# This is the position of class self
prepend M3
prepend M4
end
p Hello.ancestors
# M4, M3, Hello, M2, M1, Object, Kernel, BasicObject</code></pre>
<p>列出类继承链的技巧:</p>
<ol>
<li><p>将 <code>include</code> 的模块按顺序排在上面部分</p></li>
<li><p>将 <code>prepend</code> 的模块按顺序排在下面部分</p></li>
<li><p>将类本身放在 <code>include</code> 和 <code>prepend</code> 的中间位置</p></li>
<li><p>继承顺序就是从下往上数,包括类本身</p></li>
</ol>
Ruby生成订单号
https://segmentfault.com/a/1190000006618739
2016-08-17T16:34:11+08:00
2016-08-17T16:34:11+08:00
Ruchee
https://segmentfault.com/u/ruchee
1
<pre><code class="ruby">Time.now.strftime("%Y%m%d%H%M%S%L") << (0..9).to_a.shuffle.join</code></pre>
<pre><code>201608171633386655489732601</code></pre>
<ol>
<li><p>没有采用数据表自增ID,订单数目不会泄露给外界</p></li>
<li><p>没有用uuid,uuid字母数字混杂,不美观且无规律</p></li>
<li><p>将时间带进去了,使订单号具有一定的可读性</p></li>
<li><p>精确到了毫秒,且在尾部附加了随机数,确保唯一</p></li>
</ol>
《Ruby元编程(第2版)》读书笔记
https://segmentfault.com/a/1190000004754565
2016-03-30T22:09:44+08:00
2016-03-30T22:09:44+08:00
Ruchee
https://segmentfault.com/u/ruchee
0
<h3>对象模型</h3>
<ul>
<li><p><code>Module#constants</code> 可以获取当前范围内所有的常量</p></li>
<li><p><code>Module.constants</code> 获取当前程序中所有顶层的常量</p></li>
<li><p><code>Module.nesting</code> 可以得到当前代码所在的路径</p></li>
<li><p><code>ClassName.ancestors</code> 可以获取类的祖先链</p></li>
</ul>
<p><code>require</code> 和 <code>load</code> 的区别:</p>
<ol>
<li><p><code>load</code> 用于加载代码,<code>require</code> 用于导入类库</p></li>
<li><p><code>require</code> 对每个文件只加载一次,而 <code>load</code> 每次调用时都会再次运行所加载的文件</p></li>
<li><p><code>load</code> 有副作用,常量(包括类)有可能污染当前程序的命名空间,<code>load('xxx.rb', true)</code> 才约等于 <code>require 'xxx.rb'</code></p></li>
</ol>
<p>方法查找口诀:向右一步,再向上</p>
<p><code>include</code> 和 <code>prepend</code> 的异同:</p>
<ol>
<li><p>共同点是,都将模块加入包含者的祖先链</p></li>
<li><p>不同点是,<code>include</code> 引入的模块在包含者的上面,<code>prepend</code> 引入的模块在包含者的下面</p></li>
</ol>
<p>每个模块都只会引入一次,如果该模块已经存在于祖先链,则再次引入不会有任何影响</p>
<p>私有规则:</p>
<ol>
<li><p>如果调用方法的接收者不是自己,那就必须明确指明接收者</p></li>
<li><p>私有方法只能通过隐性的接收者调用</p></li>
</ol>
<p>顶层上下文的 <code>self</code> 是 <code>main</code> 对象</p>
<p>在类和模块的定义中,在任何方法定义以外,<code>self</code> 就是类或模块本身</p>
<p><code>refine</code> 和打开类的异同:</p>
<ol>
<li><p>两者都可以打开类定义,给类添加新的方法</p></li>
<li><p>打开类全局有效,而 <code>refine</code> 只在 <code>using</code> 以后并在 <code>using</code> 作用域以内才有效</p></li>
</ol>
<p>小结:</p>
<ul>
<li><p>对象由一组实例变量和类的引用组成</p></li>
<li><p>对象的方法存在于对象所属的类中</p></li>
<li><p>类本身是 <code>Class</code> 类的对象</p></li>
<li><p><code>Class</code> 类是 <code>Module</code> 的子类,类只是比模块多了 <code>new</code> 和 <code>superclass</code> 方法</p></li>
<li><p>类祖先链的最顶端是 <code>BasicObject</code></p></li>
<li><p>实例变量永远被认为是 <code>self</code> 的实例变量</p></li>
</ul>
<h3>方法</h3>
<p>动态派发:<code>person.hello('Ruchee')</code> 与 <code>person.send(:hello, 'Ruchee')</code> 等价<br>可以用 <code>send</code> 调用任何方法,包括私有方法<br>可以用 <code>public_send</code> 限制对私有方法的调用</p>
<p>动态方法:使用 <code>define_method</code> 来定义方法</p>
<p>幽灵方法:使用 <code>method_missing</code> 截取所有未定义的方法调用</p>
<p>动态代理:用幽灵方法捕获方法调用,并转发给另外一个对象</p>
<p>每次覆写 <code>method_missing</code> 方法时,最好也同时覆写 <code>respond_to_missing?</code> 方法,以使得可以用 <code>respond_to_missing?</code> 来正确检测是不是存在某幽灵方法</p>
<p>对于方法,找不到时会被 <code>method_missing</code> 截取,而对于常量,找不到时同样会被一个叫 <code>const_missing</code> 的方法截取</p>
<p>白板类:拥有极少方法的类,可以避免祖先链中存在同名方法而导致 <code>method_missing</code> 调用不到的问题</p>
<p><code>Module#undef_method</code> 和 <code>Module#remove_method</code> 的异同:</p>
<ol>
<li><p>相同点都是删除方法</p></li>
<li><p><code>undef_method</code> 删除所有的方法,包括继承来的</p></li>
<li><p><code>remove_method</code> 只删除自己的方法,继承来的方法保留</p></li>
</ol>
<h3>代码块</h3>
<p>可以用 <code>block_given?</code> 检测方法调用是否有传递代码块,代码块也就是闭包</p>
<p>全局变量可以在任何作用域中访问和修改</p>
<p>三个作用域门:<code>class</code>、<code>module</code>、<code>def</code></p>
<p>穿越作用域门:</p>
<ul>
<li><p>用 <code>Class.new</code> 穿越 <code>class</code> 作用域</p></li>
<li><p>用 <code>Module.new</code> 穿越 <code>module</code> 作用域</p></li>
<li><p>用 <code>define_method</code> 穿越 <code>def</code> 作用域</p></li>
</ul>
<p>上下文探针:</p>
<ul>
<li><p><code>instance_val</code> 在一个对象的上下文中执行代码块</p></li>
<li><p><code>instance_exec</code> 和 <code>instance_val</code> 功能基本一致,但允许给代码块传入参数</p></li>
</ul>
<p>延迟执行:将代码块转成 <code>proc</code> 存储,后续再用 <code>Proc#call</code> 调用执行</p>
<p>创建 <code>proc</code> 的几种方法,以下各代码段作用等价</p>
<pre><code class="ruby">inc = Proc.new { |x| x + 1 }
puts inc.call(10)
inc = lambda { |x| x + 1 }
puts inc.call(10)
inc = ->x { x + 1 }
puts inc.call(10)
def create_proc (&block)
block
end
inc = create_proc { |x| x + 1 }
puts inc.call(10)
def test (&inc)
inc.call(10)
end
puts test { |x| x + 1 }
def test
yield 10
end
puts test { |x| x + 1 }
class Test
def inc (x)
x + 1
end
end
inc = Test.new.method :inc
puts inc.call(10)</code></pre>
<p>定义方法时,最后一个参数以 <code>&</code> 打头可以将传递给该方法的代码块转成 <code>proc</code>;而调用方法时,在保存 <code>proc</code> 的变量名前加 <code>&</code> 可以将 <code>proc</code> 转回代码块</p>
<p><code>Proc</code> 与 <code>Lambda</code> 的区别:</p>
<ul>
<li><p>用 <code>lambda</code> 方法创建的 <code>Proc</code> 称为 <code>lambda</code>,而用其他方式创建的则称为 <code>proc</code>(可以用 <code>Proc#lambda?</code> 检测是不是 <code>lambda</code>)</p></li>
<li><p><code>lambda</code> 里面的 <code>return</code> 仅从该 <code>lambda</code> 中返回,而 <code>proc</code> 里面的 <code>return</code> 却是从定义该 <code>proc</code> 的作用域中返回</p></li>
<li><p>在参数适应能力上,<code>proc</code> 适应能力更强,而 <code>lambda</code> 对传递的参数个数要求严格</p></li>
<li><p>综合 <code>return</code> 和参数,<code>lambda</code> 的表现更像真实的方法:严格检查参数个数,只从自己的代码区域返回</p></li>
</ul>
<p><code>Proc</code> 和 <code>Lambda</code> <code>return</code> 的差异代码示例:</p>
<pre><code class="ruby">def test
l = -> { return 10 }
l.call * 2
end
puts test # 输出 20
def test
p = Proc.new { return 10 }
p.call * 2 # 这一行代码压根执行不到,前一行就已经返回了
end
puts test # 输出 10
</code></pre>
<p>可以用 <code>Method#unbind</code> 或 <code>Module#instance_method</code> 将一个方法变成自由方法,也可以用 <code>UnboundMethod#bind</code> 或 <code>Module#define_method</code> 再次将自由方法绑定到某个对象</p>
<h3>类定义</h3>
<p><code>Module#class_eval</code> 可以在不使用 <code>class</code> 关键字的情况下修改当前类</p>
<p><code>Module#module_eval</code> 是 <code>Module#class_eval</code> 的别名</p>
<p><code>class_eval</code> 和 <code>module_eval</code> 同样有孪生方法 <code>class_exec</code> 和 <code>module_exec</code></p>
<p>类变量和类实例变量的区别:</p>
<ul>
<li><p>类变量以 <code>@@</code> 打头,而类实例变量以 <code>@</code> 打头</p></li>
<li><p>类变量可以被子类或类的实例所使用</p></li>
<li><p>类变量的值可以在类定义以外的区域被修改,尽管会得到一个警告</p></li>
</ul>
<p>单件方法:在单个对象上定义,且只对单个对象生效的方法</p>
<p>可以使用 <code>def obj.xxx</code> 定义单件方法,也可以使用 <code>Object#define_singleton_method</code> 方法来定义,可以用 <code>Object.singleton_methods</code> 获取某个对象全部的单件方法</p>
<p>类方法的实质:类方法其实就是一个类的单件方法</p>
<p>单件类:</p>
<ul>
<li><p>保存一个对象所有的单件方法</p></li>
<li><p>只有一个实例,不能被继承</p></li>
<li><p>在类继承链中不可见,只能用 <code>Object#singleton_class</code> 或 <code>class<<</code> 来获取</p></li>
<li><p>如果将单件类从继承链标识出来,它是在该对象所属类下方的,也就是对象的方法调用是先查找的单件类,再查找的类本身</p></li>
</ul>
<p>单件类的超类是该单件类所归属类的超类的单件类,正因为如此,子类才可以调用到父类的类方法,因为类方法就是类的单件方法,保存在单件类之中,而方法调用会先查找单件类</p>
<p>定义类方法的三种方式:</p>
<pre><code class="ruby">def Hello.hello
# xxx
end
class Hello
def self.hello
# xxx
end
end
class Hello
class <<self
def hello
# xxx
end
end
end</code></pre>
<p><code>include</code> 和 <code>extend</code></p>
<ul>
<li><p><code>include</code> 是在类层面包含模块,所包含模块的方法将成为类的实例方法</p></li>
<li><p><code>extend</code> 是在单件类层面包含模块,所包含模块的方法将成为单件类的实例方法,也就是类的类方法</p></li>
</ul>
<p><code>extend</code> 实例:</p>
<pre><code class="ruby">module HelloModule
def hello
"Hello, World"
end
end
class HelloClass
# 写法1
class <<self
include HelloModule
end
# 写法2
extend HelloModule
end
puts HelloClass.hello</code></pre>
<p>编写环绕别名的三个步骤:</p>
<ol>
<li><p>给方法定义一个别名</p></li>
<li><p>重定义这个方法</p></li>
<li><p>在新方法中调用老方法</p></li>
</ol>
<h3>编写代码的代码</h3>
<p><code>Binding</code>:一个用对象表示的完整作用域,可以用 <code>Kernel#binding</code> 方法捕获当前作用域,然后可以通过 <code>eval</code> 方法在这个绑定对象所携带的作用域中执行代码</p>
<p><code>TOPLEVEL_BINDING</code>:表示顶级作用域的绑定对象,可以在程序的任何地方访问到</p>
<p>全局变量 <code>$SAFE</code> 用于控制安全级别,默认为 <code>0</code>,可设置值为 <code>0</code> 到 <code>3</code></p>
<p><code>Object#instance_variable_set</code> 和 <code>Object#instance_variable_get</code> 可用来操作实例变量</p>
给ctags添加对Elixir的支持
https://segmentfault.com/a/1190000003058105
2015-08-06T10:22:33+08:00
2015-08-06T10:22:33+08:00
Ruchee
https://segmentfault.com/u/ruchee
0
<h2>背景概述</h2>
<p>ctags 官方已经许久未更新了,截至本文写作时止,最后一次更新在 2009-07-09,所以很多新出的语言都没能得到支持</p>
<p>现在 Github 上有一个 fork 出来的项目叫 universal-ctags,它拾起了对 ctags 的更新,但是很遗憾,Elixir 也暂未得到支持</p>
<h2>自己动手丰衣足食</h2>
<p>好在 ctags 支持一个自定义的配置文件,名为 .ctags,可以在这里书写规则实现对未知编程语言的解析</p>
<p>下面是针对 Elixir 的配置</p>
<pre><code>--langdef=Elixir
--langmap=Elixir:.ex.exs
--regex-Elixir=/^[ \t]*def(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\2/f,functions,functions (def ...)/
--regex-Elixir=/^[ \t]*defcallback[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\1/c,callbacks,callbacks (defcallback ...)/
--regex-Elixir=/^[ \t]*defdelegate[ \t]+([a-z_][a-zA-Z0-9_?!]*)/\1/d,delegates,delegates (defdelegate ...)/
--regex-Elixir=/^[ \t]*defexception[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/e,exceptions,exceptions (defexception ...)/
--regex-Elixir=/^[ \t]*defimpl[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/i,implementations,implementations (defimpl ...)/
--regex-Elixir=/^[ \t]*defmacro(p?)[ \t]+([a-z_][a-zA-Z0-9_?!]*)\(/\2/a,macros,macros (defmacro ...)/
--regex-Elixir=/^[ \t]*defmacro(p?)[ \t]+([a-zA-Z0-9_?!]+)?[ \t]+([^ \tA-Za-z0-9_]+)[ \t]*[a-zA-Z0-9_!?!]/\3/o,operators,operators (e.g. "defmacro a <<< b")/
--regex-Elixir=/^[ \t]*defmodule[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/m,modules,modules (defmodule ...)/
--regex-Elixir=/^[ \t]*defprotocol[ \t]+([A-Z][a-zA-Z0-9_]*\.)*([A-Z][a-zA-Z0-9_?!]*)/\2/p,protocols,protocols (defprotocol...)/
--regex-Elixir=/^[ \t]*Record\.defrecord[ \t]+:([a-zA-Z0-9_]+)/\1/r,records,records (defrecord...)/
</code></pre>
<p>把上述内容保存到文本文件,并命名为 .ctags,MacOSX 和 Linux 放置到自己的家目录下即可;Windows 下得先设置个名为 HOMEPATH 的环境变量,然后将 .ctags 放置到该环境变量所指路径下</p>
<p>打开命令行,执行 ctags --list-languages,在输出的信息中能找到 Elixir 则说明配置成功</p>
<h2>怎么可能少得了Vim</h2>
<p>在 Vim 里面即时浏览代码结构,首推 tagbar 插件,这里就不介绍怎么安装、怎么使用了,下面是添加对 Elixir 的支持,将其写在 .vimrc 中即可</p>
<pre><code>let g:tagbar_type_elixir = {'ctagstype': 'elixir', 'kinds': ['f:functions:0:0', 'c:callbacks:0:0', 'd:delegates:0:0', 'e:exceptions:0:0', 'i:implementations:0:0', 'a:macros:0:0', 'o:operators:0:0', 'm:modules:0:0', 'p:protocols:0:0', 'r:records:0:0'], 'sro': '.', 'kind2scope': {'m': 'modules'}, 'scope2kind': {'modules': 'm'}}
</code></pre>
Nginx手机浏览自动跳转
https://segmentfault.com/a/1190000003040197
2015-07-31T19:26:38+08:00
2015-07-31T19:26:38+08:00
Ruchee
https://segmentfault.com/u/ruchee
1
<p>需求</p>
<p>PC站地址:<a rel="nofollow" href="http://example.com">http://example.com</a><br>
PC站文章地址:<a rel="nofollow" href="http://example.com/news/article.html">http://example.com/news/article.html</a></p>
<p>手机站地址:<a rel="nofollow" href="http://example.com/m">http://example.com/m</a><br>
手机站文章地址:<a rel="nofollow" href="http://example.com/m/news/article.html">http://example.com/m/news/article.html</a></p>
<p>现在需要当手机访问PC站页面时自动跳转到对应的手机站页面</p>
<hr>
<p>NGINX配置</p>
<pre><code>server {
listen 80;
server_name example.com;
root /path/to/example.com;
# 检测是不是手机访问
set $mobile_rewrite do_not_perform;
if ($http_user_agent ~* "(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino") {
set $mobile_rewrite perform;
}
if ($http_user_agent ~* "^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-)") {
set $mobile_rewrite perform;
}
# 检测访问的是不是PC版页面
if ($document_uri !~ '^/m/') {
set $mobile_rewrite "${mobile_rewrite}pc";
}
location / {
# 手机访问PC版页面,则路由前面加/m/跳转
if ($mobile_rewrite = performpc) {
rewrite ^ /m$uri redirect;
}
index index.html;
try_files $uri $uri/;
}
}
</code></pre>
Composer OpenSSL 错误解决办法
https://segmentfault.com/a/1190000002460373
2015-01-04T10:04:03+08:00
2015-01-04T10:04:03+08:00
Ruchee
https://segmentfault.com/u/ruchee
2
<p><code>Windows</code> 下 <code>Composer</code> 爆出错误:<code>Failed to enable crypto</code>。原因是证书验证失败</p>
<p>下面是解决方法:<br>
1. 上 <code>http://curl.haxx.se/docs/caextract.html</code> 下载最新的 <code>cacert.pem</code> 文件<br>
2. 将该文件丢到某个目录下,如 <code>D:\Ruchee\PHP\extras\ssl</code><br>
3. 找到 <code>PHP.ini</code> 文件中的 <code>openssl.cafile</code> 选项,设置为 <code>openssl.cafile = D:/Ruchee/PHP/extras/ssl/cacert.pem</code></p>
<p>如此就可以了</p>
Linode 安装 Ubuntu 主机记录
https://segmentfault.com/a/1190000002456481
2015-01-01T19:16:48+08:00
2015-01-01T19:16:48+08:00
Ruchee
https://segmentfault.com/u/ruchee
0
<p>指定语言:<code>sudo locale-gen --lang zh_CN.UTF-8</code></p>
<p>校正时区:<code>sudo dpkg-reconfigure tzdata</code></p>
<p>更新软件源:<code>sudo apt-get update</code></p>
<p>更新软件包:<code>sudo apt-get upgrade</code></p>
ssh常用操作
https://segmentfault.com/a/1190000002446902
2014-12-26T15:27:43+08:00
2014-12-26T15:27:43+08:00
Ruchee
https://segmentfault.com/u/ruchee
0
<ul>
<li>登录:<code>ssh 用户名@主机域名或IP地址</code>
</li>
<li>上传:<code>scp 本地文件路径 用户名@主机域名或IP地址:远程保存路径</code>
</li>
<li>下载:<code>scp 用户名@主机域名或IP地址:远程文件路径 本地保存路径</code>
</li>
</ul>
<p>常用选项<br>
* <code>-v</code>:显示传输进度<br>
* <code>-r</code>:递归上传或下载文件夹<br>
* <code>-P 端口号</code>:设置端口号</p>
JavaScript 绑定事件时传递数据
https://segmentfault.com/a/1190000002440325
2014-12-23T18:27:24+08:00
2014-12-23T18:27:24+08:00
Ruchee
https://segmentfault.com/u/ruchee
4
<pre><code>javascript</code><code>var data = {
name: 'Ruchee',
email: 'my@ruchee.com'
};
data.handleEvent = function (e) {
console.log(this);
};
document.getElementById('test_button').addEventListener('click', data, false);
</code></pre>
<p>要点:<br>
1. 绑定事件时传递数据本身<br>
2. 传递的数据中需要定义有一个 <code>handleEvent</code> 方法来负责事件响应</p>
JavaScript trim 实现(去除字符串首尾指定字符)
https://segmentfault.com/a/1190000002438098
2014-12-22T17:10:48+08:00
2014-12-22T17:10:48+08:00
Ruchee
https://segmentfault.com/u/ruchee
3
<pre><code>javascript</code><code>String.prototype.trim = function (char, type) {
if (char) {
if (type == 'left') {
return this.replace(new RegExp('^\\'+char+'+', 'g'), '');
} else if (type == 'right') {
return this.replace(new RegExp('\\'+char+'+$', 'g'), '');
}
return this.replace(new RegExp('^\\'+char+'+|\\'+char+'+$', 'g'), '');
}
return this.replace(/^\s+|\s+$/g, '');
};
// 去除字符串首尾的全部空白
var str = ' Ruchee ';
console.log('xxx' + str.trim() + 'xxx'); // xxxRucheexxx
// 去除字符串左侧空白
str = ' Ruchee ';
console.log('xxx' + str.trim(' ', 'left') + 'xxx'); // xxxRuchee xxx
// 去除字符串右侧空白
str = ' Ruchee ';
console.log('xxx' + str.trim(' ', 'right') + 'xxx'); // xxx Rucheexxx
// 去除字符串两侧指定字符
str = '/Ruchee/';
console.log(str.trim('/')); // Ruchee
// 去除字符串左侧指定字符
str = '/Ruchee/';
console.log(str.trim('/', 'left')); // Ruchee/
// 去除字符串右侧指定字符
str = '/Ruchee/';
console.log(str.trim('/', 'right')); // /Ruchee
</code></pre>
图片转 base64 编码显示(PHP)
https://segmentfault.com/a/1190000002435029
2014-12-20T15:01:51+08:00
2014-12-20T15:01:51+08:00
Ruchee
https://segmentfault.com/u/ruchee
1
<pre><code>php</code><code><img src="data:image/jpg;base64,<?= base64_encode(file_get_contents(__DIR__.'/ruchee.jpg')) ?>">
</code></pre>
PHP 切换 Session
https://segmentfault.com/a/1190000002433962
2014-12-19T17:47:57+08:00
2014-12-19T17:47:57+08:00
Ruchee
https://segmentfault.com/u/ruchee
1
<pre><code>php</code><code><?php
// 开启会话a
session_id('a');
session_start();
$_SESSION['name'] = 'Ruchee';
var_dump($_SESSION);
// 停止会话a的写入
session_write_close();
// 切换到会话b
session_id('b');
session_start();
// 检验有没有切换成功,正常情况下此处应该为空数组
var_dump($_SESSION);
</code></pre>