2023-10-30T08:12:19+00:00
https://blog.lisong.hn.cn
webrtc通信实践
2022-11-15T00:00:00+00:00
https://blog.lisong.hn.cn/nodejs/2022/11/15/webrtc通信实践
<h2 id="centos7-下安装-coturn">centos7 下安装 coturn</h2>
<h3 id="安装相关依赖">安装相关依赖</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>yum <span class="nb">install</span> <span class="nt">-y</span> make gcc cc gcc-c++ wget openssl-devel libevent libevent-devel openssl
yum <span class="nb">install </span>git
</code></pre></div></div>
<h3 id="下载编译安装coturn开源项目">下载编译安装coturn开源项目</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone https://github.com/coturn/coturn
<span class="nb">cd </span>coturn
./configure
make
make <span class="nb">install</span>
</code></pre></div></div>
<h3 id="查看是否安装成功">查看是否安装成功</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>which turnserver
</code></pre></div></div>
<h3 id="将usrlocaletc目录下的turnserverconfdefault文件复制一份文件名为turnserverconf">将/usr/local/etc/目录下的turnserver.conf.default文件复制一份,文件名为turnserver.conf</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd</span> /usr/local/etc/
<span class="nb">cp </span>turnserver.conf.default turnserver.conf
</code></pre></div></div>
<h3 id="查看网卡记录网卡名称和内网地址ifconfig">查看网卡,记录网卡名称和内网地址:ifconfig</h3>
<p><img src="https://wanls4583.github.io/images/posts/nodejs/webrtc-1.webp" alt="" /></p>
<h3 id="cert和pkey配置的自签名证书用openssl命令生成提示的相关信息随便填写即可">cert和pkey配置的自签名证书用Openssl命令生成,提示的相关信息随便填写即可</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>openssl req <span class="nt">-x509</span> <span class="nt">-newkey</span> rsa:2048 <span class="nt">-keyout</span> /usr/local/etc/turn_server_pkey.pem <span class="nt">-out</span> /usr/local/etc/turn_server_cert.pem <span class="nt">-days</span> 99999 <span class="nt">-nodes</span>
</code></pre></div></div>
<h3 id="修改配置文件信息vim-usrlocaletcturnserverconf">修改配置文件信息:vim /usr/local/etc/turnserver.conf</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 网卡名</span>
relay-device<span class="o">=</span>eth0
<span class="c">#内网IP</span>
listening-ip<span class="o">=</span>172.16.0.5
listening-port<span class="o">=</span>3478
<span class="c">#内网IP</span>
relay-ip<span class="o">=</span>172.16.0.5
tls-listening-port<span class="o">=</span>5349
<span class="c"># 外网IP</span>
external-ip<span class="o">=</span>134.xxx.xxx.xxx
relay-threads<span class="o">=</span>500
<span class="c">#打开密码验证</span>
lt-cred-mech
<span class="nv">cert</span><span class="o">=</span>/usr/local/etc/turn_server_cert.pem
<span class="nv">pkey</span><span class="o">=</span>/usr/local/etc/turn_server_pkey.pem
min-port<span class="o">=</span>40000
max-port<span class="o">=</span>65535
<span class="c">#设置用户名和密码,创建IceServer时使用</span>
<span class="nv">user</span><span class="o">=</span>admin:123456
<span class="c"># 外网IP绑定的域名</span>
<span class="nv">realm</span><span class="o">=</span>lisong.hn.cn
<span class="c"># 服务器名称,用于OAuth认证,默认和realm相同,部分浏览器本段不设可能会引发cors错误。</span>
server-name<span class="o">=</span>lisong.hn.cn
<span class="c"># 认证密码,和前面设置的密码保持一致</span>
cli-password<span class="o">=</span>123456
</code></pre></div></div>
<h3 id="添加3478端口的tcpudp规则">添加3478端口的tcp/udp规则</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#开放端口</span>
firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-port</span><span class="o">=</span>3478/udp <span class="nt">--permanent</span>
firewall-cmd <span class="nt">--zone</span><span class="o">=</span>public <span class="nt">--add-port</span><span class="o">=</span>3478/tcp <span class="nt">--permanent</span>
<span class="c">#刷新防火墙</span>
firewall-cmd <span class="nt">--reload</span>
<span class="c">#查看当前开放的端口</span>
firewall-cmd <span class="nt">--list-port</span>
</code></pre></div></div>
<h3 id="启动服务turnserver--o--a--f备注turnserver命令会自动寻找到turnserverconf文件的位置">启动服务:turnserver -o -a -f。备注:turnserver命令会自动寻找到turnserver.conf文件的位置。</h3>
<h3 id="终止服务">终止服务</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#搜索 turnserveru 进程</span>
ps <span class="nt">-ef</span> | <span class="nb">grep </span>turnserver
<span class="c">#杀掉进程(pid换成进程号)</span>
<span class="nb">kill</span> <span class="nt">-9</span> pid
</code></pre></div></div>
<h3 id="在线检测ice穿透httpswebrtcgithubiosamplessrccontentpeerconnectiontrickle-ice">在线检测ICE穿透:<a href="https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/">https://webrtc.github.io/samples/src/content/peerconnection/trickle-ice/</a></h3>
<p><img src="https://wanls4583.github.io/images/posts/nodejs/webrtc-2.webp" alt="" /></p>
<h2 id="客户端">客户端</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">http-equiv=</span><span class="s">"X-UA-Compatible"</span> <span class="na">content=</span><span class="s">"IE=edge"</span><span class="nt">></span>
<span class="nt"><meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width, initial-scale=1.0"</span><span class="nt">></span>
<span class="nt"><title></span>webrtc<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"./adapter-latest.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"doOffer()"</span><span class="nt">></span>加入会议<span class="nt"></button></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"videos"</span><span class="nt">></span>
<span class="nt"><video</span> <span class="na">id=</span><span class="s">"localVideo"</span> <span class="na">autoplay</span> <span class="na">muted</span> <span class="na">playsinline</span><span class="nt">></span>本地窗口<span class="nt"></video></span>
<span class="nt"><video</span> <span class="na">id=</span><span class="s">"remoteVideo"</span> <span class="na">autoplay</span> <span class="na">playsinline</span><span class="nt">></span>远端窗口<span class="nt"></video></span>
<span class="nt"></div></span>
<span class="nt"><script></span>
<span class="kd">var</span> <span class="nx">DO_OFFER</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">DO_ANSWER</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">SET_DESC</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">ICE_CANDIDATE</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">localVideo</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">#localVideo</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">remoteVideo</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">#remoteVideo</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">zeroRTCEngine</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">localStream</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">remoteStream</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">candidate</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">offerSession</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">answerSession</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="kd">class</span> <span class="nx">ZeroRTCEngine</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">(</span><span class="nx">wsUrl</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">wsUrl</span> <span class="o">=</span> <span class="nx">wsUrl</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">signaling</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">createWebsocket</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">createWebsocket</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">signaling</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocket</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">wsUrl</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">signaling</span><span class="p">.</span><span class="nx">onopen</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">websocket open</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">signaling</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">;</span>
<span class="nx">message</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">message:</span><span class="dl">'</span><span class="p">,</span> <span class="nx">message</span><span class="p">.</span><span class="nx">type</span><span class="p">);</span>
<span class="k">switch</span> <span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="nx">DO_ANSWER</span><span class="p">:</span>
<span class="nx">doAnswer</span><span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="nx">ICE_CANDIDATE</span><span class="p">:</span>
<span class="nx">addIceCandidate</span><span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="nx">SET_DESC</span><span class="p">:</span>
<span class="nx">setRemoteDescription</span><span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">signaling</span><span class="p">.</span><span class="nx">onerror</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">onError: </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">signaling</span><span class="p">.</span><span class="nx">onclose</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">onClose -> code: </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">event</span><span class="p">.</span><span class="nx">code</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">, reason:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">EventTarget</span><span class="p">.</span><span class="nx">reason</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">sendMessage</span><span class="p">(</span><span class="nx">message</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">signaling</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">message</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">init</span><span class="p">();</span>
<span class="kd">function</span> <span class="nx">init</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">zeroRTCEngine</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ZeroRTCEngine</span><span class="p">(</span><span class="dl">'</span><span class="s1">ws://127.0.0.1:8081/</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">navigator</span><span class="p">.</span><span class="nx">mediaDevices</span><span class="p">.</span><span class="nx">getUserMedia</span><span class="p">({</span>
<span class="na">audio</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">video</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">stream</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">localVideo</span><span class="p">.</span><span class="nx">srcObject</span> <span class="o">=</span> <span class="nx">stream</span><span class="p">;</span>
<span class="nx">localStream</span> <span class="o">=</span> <span class="nx">stream</span><span class="p">;</span>
<span class="nx">createPeerConnection</span><span class="p">();</span>
<span class="p">})</span>
<span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="dl">"</span><span class="s2">getUserMedia() error: </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">e</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">createPeerConnection</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">defaultConfiguration</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">bundlePolicy</span><span class="p">:</span> <span class="dl">"</span><span class="s2">max-bundle</span><span class="dl">"</span><span class="p">,</span>
<span class="na">rtcpMuxPolicy</span><span class="p">:</span> <span class="dl">"</span><span class="s2">require</span><span class="dl">"</span><span class="p">,</span>
<span class="na">iceTransportPolicy</span><span class="p">:</span> <span class="dl">"</span><span class="s2">all</span><span class="dl">"</span><span class="p">,</span>
<span class="c1">//iceTransportPolicy: "relay", </span>
<span class="c1">// 修改ice数组测试效果,需要进行封装</span>
<span class="na">iceServers</span><span class="p">:</span> <span class="p">[{</span>
<span class="dl">"</span><span class="s2">urls</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>
<span class="dl">"</span><span class="s2">turn:bwg.lisong.hn.cn:3478?transport=udp</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">turn:bwg.lisong.hn.cn:3478?transport=tcp</span><span class="dl">"</span> <span class="c1">// 可以插入多个进行备选</span>
<span class="p">],</span>
<span class="dl">"</span><span class="s2">username</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">credential</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">123456</span><span class="dl">"</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="dl">"</span><span class="s2">urls</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>
<span class="dl">"</span><span class="s2">stun:bwg.lisong.hn.cn:3478</span><span class="dl">"</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">};</span>
<span class="nx">pc</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">RTCPeerConnection</span><span class="p">(</span><span class="nx">defaultConfiguration</span><span class="p">);</span> <span class="c1">// 音视频通话的核心类</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">onicecandidate</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">"</span><span class="s2">onicecandidate</span><span class="dl">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">candidate</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">candidate</span> <span class="o">=</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">sdpMLineIndex</span><span class="dl">'</span><span class="p">:</span> <span class="nx">event</span><span class="p">.</span><span class="nx">candidate</span><span class="p">.</span><span class="nx">sdpMLineIndex</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">sdpMid</span><span class="dl">'</span><span class="p">:</span> <span class="nx">event</span><span class="p">.</span><span class="nx">candidate</span><span class="p">.</span><span class="nx">sdpMid</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">candidate</span><span class="dl">'</span><span class="p">:</span> <span class="nx">event</span><span class="p">.</span><span class="nx">candidate</span><span class="p">.</span><span class="nx">candidate</span>
<span class="p">};</span>
<span class="nx">zeroRTCEngine</span><span class="p">.</span><span class="nx">sendMessage</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span>
<span class="na">type</span><span class="p">:</span> <span class="nx">ICE_CANDIDATE</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">candidate</span>
<span class="p">}));</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">warn</span><span class="p">(</span><span class="dl">"</span><span class="s2">End of candidates</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">ontrack</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">ontrack</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">remoteStream</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">streams</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="nx">remoteVideo</span><span class="p">.</span><span class="nx">srcObject</span> <span class="o">=</span> <span class="nx">remoteStream</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">onconnectionstatechange</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">pc</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">"</span><span class="s2">ConnectionState -> </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">pc</span><span class="p">.</span><span class="nx">connectionState</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">oniceconnectionstatechange</span> <span class="o">=</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">pc</span> <span class="o">!=</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">info</span><span class="p">(</span><span class="dl">"</span><span class="s2">IceConnectionState -> </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">pc</span><span class="p">.</span><span class="nx">iceConnectionState</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">localStream</span><span class="p">.</span><span class="nx">getTracks</span><span class="p">().</span><span class="nx">forEach</span><span class="p">((</span><span class="nx">track</span><span class="p">)</span> <span class="o">=></span> <span class="nx">pc</span><span class="p">.</span><span class="nx">addTrack</span><span class="p">(</span><span class="nx">track</span><span class="p">,</span> <span class="nx">localStream</span><span class="p">));</span> <span class="c1">// 把本地流设置给RTCPeerConnection</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">doOffer</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">pc</span> <span class="o">==</span> <span class="kc">null</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">createPeerConnection</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">createOffer</span><span class="p">().</span><span class="nx">then</span><span class="p">((</span><span class="nx">session</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">setLocalDescription</span><span class="p">(</span><span class="nx">session</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">offerSession</span> <span class="o">=</span> <span class="nx">session</span><span class="p">;</span>
<span class="nx">zeroRTCEngine</span><span class="p">.</span><span class="nx">sendMessage</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span>
<span class="na">type</span><span class="p">:</span> <span class="nx">DO_OFFER</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">session</span>
<span class="p">}));</span>
<span class="p">})</span>
<span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">"</span><span class="s2">offer setLocalDescription failed: </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">doAnswer</span><span class="p">(</span><span class="nx">session</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">setRemoteDescription</span><span class="p">(</span><span class="nx">session</span><span class="p">);</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">createAnswer</span><span class="p">().</span><span class="nx">then</span><span class="p">((</span><span class="nx">session</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">setLocalDescription</span><span class="p">(</span><span class="nx">session</span><span class="p">)</span>
<span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">answerSession</span> <span class="o">=</span> <span class="nx">session</span><span class="p">;</span>
<span class="nx">zeroRTCEngine</span><span class="p">.</span><span class="nx">sendMessage</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">({</span>
<span class="na">type</span><span class="p">:</span> <span class="nx">DO_ANSWER</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">session</span>
<span class="p">}));</span>
<span class="p">})</span>
<span class="p">.</span><span class="k">catch</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">error</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">"</span><span class="s2">answer setLocalDescription failed: </span><span class="dl">"</span> <span class="o">+</span> <span class="nx">error</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">addIceCandidate</span><span class="p">(</span><span class="nx">candidate</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">addIceCandidate</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">candidate</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">RTCIceCandidate</span><span class="p">(</span><span class="nx">candidate</span><span class="p">);</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">addIceCandidate</span><span class="p">(</span><span class="nx">candidate</span><span class="p">).</span><span class="k">catch</span><span class="p">(</span><span class="nx">e</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">error</span><span class="p">(</span><span class="dl">"</span><span class="s2">addIceCandidate failed:</span><span class="dl">"</span> <span class="o">+</span> <span class="nx">e</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">setRemoteDescription</span><span class="p">(</span><span class="nx">session</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">setRemoteDescription</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">pc</span><span class="p">.</span><span class="nx">setRemoteDescription</span><span class="p">(</span><span class="nx">session</span><span class="p">);</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<h2 id="服务端">服务端</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">WebSocket</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">ws</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">connMap</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="nx">id</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">DO_OFFER</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">DO_ANSWER</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">SET_DESC</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">ICE_CANDIDATE</span> <span class="o">=</span> <span class="mi">4</span><span class="p">;</span>
<span class="kd">const</span> <span class="nx">webSocketServer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">WebSocket</span><span class="p">.</span><span class="nx">Server</span><span class="p">({</span>
<span class="na">port</span><span class="p">:</span> <span class="mi">8081</span>
<span class="p">});</span>
<span class="nx">webSocketServer</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">listening</span><span class="dl">'</span><span class="p">,</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">web socket begins listening</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">webSocketServer</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">connection</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="nx">connection</span><span class="p">(</span><span class="nx">conn</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">userId</span> <span class="o">=</span> <span class="nx">id</span><span class="o">++</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">New connection:</span><span class="dl">"</span><span class="p">,</span> <span class="nx">userId</span><span class="p">);</span>
<span class="nx">connMap</span><span class="p">[</span><span class="nx">userId</span><span class="p">]</span> <span class="o">=</span> <span class="nx">conn</span><span class="p">;</span>
<span class="nx">conn</span><span class="p">.</span><span class="nx">userId</span> <span class="o">=</span> <span class="nx">userId</span><span class="p">;</span>
<span class="nx">conn</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">message</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">message</span> <span class="o">=</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">str</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">recieve</span><span class="dl">'</span><span class="p">,</span> <span class="nx">userId</span><span class="p">,</span> <span class="nx">message</span><span class="p">.</span><span class="nx">type</span><span class="p">);</span>
<span class="k">switch</span> <span class="p">(</span><span class="nx">message</span><span class="p">.</span><span class="nx">type</span><span class="p">)</span> <span class="p">{</span>
<span class="k">case</span> <span class="na">DO_OFFER</span><span class="p">:</span>
<span class="nx">broadcast</span><span class="p">(</span><span class="nx">userId</span><span class="p">,</span> <span class="p">{</span>
<span class="na">type</span><span class="p">:</span> <span class="nx">DO_ANSWER</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">message</span><span class="p">.</span><span class="nx">data</span>
<span class="p">});</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="na">ICE_CANDIDATE</span><span class="p">:</span>
<span class="nx">broadcast</span><span class="p">(</span><span class="nx">userId</span><span class="p">,</span> <span class="p">{</span>
<span class="na">type</span><span class="p">:</span> <span class="nx">ICE_CANDIDATE</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">message</span><span class="p">.</span><span class="nx">data</span>
<span class="p">});</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="na">DO_ANSWER</span><span class="p">:</span>
<span class="nx">broadcast</span><span class="p">(</span><span class="nx">userId</span><span class="p">,</span> <span class="p">{</span>
<span class="na">type</span><span class="p">:</span> <span class="nx">SET_DESC</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="nx">message</span><span class="p">.</span><span class="nx">data</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">conn</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">close</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">code</span><span class="p">,</span> <span class="nx">reason</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">Connection closed:</span><span class="dl">"</span><span class="p">,</span> <span class="nx">userId</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="kd">function</span> <span class="nx">broadcast</span><span class="p">(</span><span class="nx">userId</span><span class="p">,</span> <span class="nx">msg</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">type</span> <span class="o">=</span> <span class="nx">msg</span><span class="p">.</span><span class="nx">type</span><span class="p">;</span>
<span class="nx">msg</span> <span class="o">=</span> <span class="k">typeof</span> <span class="nx">msg</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">object</span><span class="dl">'</span> <span class="p">?</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">msg</span><span class="p">)</span> <span class="p">:</span> <span class="nx">msg</span><span class="p">;</span>
<span class="nx">webSocketServer</span><span class="p">.</span><span class="nx">clients</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">conn</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">conn</span><span class="p">.</span><span class="nx">userId</span> <span class="o">!==</span> <span class="nx">userId</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">conn</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="nx">msg</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">send</span><span class="dl">'</span><span class="p">,</span> <span class="nx">conn</span><span class="p">.</span><span class="nx">userId</span><span class="p">,</span> <span class="nx">type</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="仓库代码httpsgithubcomwanls4583webrtcgit">仓库代码:<a href="https://github.com/wanls4583/webrtc.git">https://github.com/wanls4583/webrtc.git</a></h2>
实现Promise
2022-11-06T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2022/11/06/实现Promise
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">class</span> <span class="nx">Promsie</span> <span class="p">{</span>
<span class="kd">constructor</span><span class="p">(</span><span class="nx">excutor</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">that</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">PromiseResult</span> <span class="o">=</span> <span class="kc">undefined</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">PromiseState</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">pending</span><span class="dl">'</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">callbacks</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">function</span> <span class="nx">resolve</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">PromiseState</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">fullfilled</span><span class="dl">'</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">PromiseResult</span> <span class="o">=</span> <span class="nx">data</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">callbacks</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">item</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">item</span><span class="p">.</span><span class="nx">onResolve</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">reject</span><span class="p">()</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">PromiseState</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">rejected</span><span class="dl">'</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">PromiseResult</span> <span class="o">=</span> <span class="nx">data</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">callbacks</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">item</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">item</span><span class="p">.</span><span class="nx">onReject</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="nx">excutor</span><span class="p">(</span><span class="nx">resolve</span><span class="p">,</span> <span class="nx">reject</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">then</span><span class="p">(</span><span class="nx">onResolve</span><span class="p">,</span> <span class="nx">onReject</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">that</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">onResolve</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">function</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">onResolve</span> <span class="o">=</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">data</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">onReject</span> <span class="o">!==</span> <span class="dl">'</span><span class="s1">function</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">onReject</span> <span class="o">=</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="k">throw</span> <span class="nx">data</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">resove</span><span class="p">,</span> <span class="nx">reject</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">function</span> <span class="nx">fun</span><span class="p">(</span><span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="kd">let</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">callback</span><span class="p">(</span><span class="nx">that</span><span class="p">.</span><span class="nx">PromiseResult</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">result</span> <span class="k">instanceof</span> <span class="nx">Promsie</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">result</span><span class="p">.</span><span class="nx">then</span><span class="p">((</span><span class="nx">r</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">resove</span><span class="p">(</span><span class="nx">r</span><span class="p">);</span>
<span class="p">},</span> <span class="p">(</span><span class="nx">r</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">reject</span><span class="p">(</span><span class="nx">r</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">resove</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">reject</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">that</span><span class="p">.</span><span class="nx">PromiseState</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">fullfilled</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">fun</span><span class="p">(</span><span class="nx">onResolve</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">that</span><span class="p">.</span><span class="nx">PromiseState</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">rejected</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">fun</span><span class="p">(</span><span class="nx">onReject</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">that</span><span class="p">.</span><span class="nx">PromiseResult</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">pending</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">callbacks</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
<span class="na">onResolve</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">fun</span><span class="p">(</span><span class="nx">onResolve</span><span class="p">);</span>
<span class="p">},</span>
<span class="na">onReject</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">fun</span><span class="p">(</span><span class="nx">onReject</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="k">catch</span><span class="p">(</span><span class="nx">onReject</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">then</span><span class="p">(</span><span class="kc">undefined</span><span class="p">,</span> <span class="nx">onReject</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
SPA路由原理
2021-11-23T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2021/11/23/SPA路由原理
<blockquote>
<p>SPA路由的实现在前端有两种方式:hash和history,其中hash的方式兼容想较好,history只适用于HTML5浏览器。</p>
</blockquote>
<h3 id="hash方式">hash方式</h3>
<p>此种方式通过改变hash值来实现路由的跳转,改变hash值并不会发生请求到后端,所以不需要后端配置路由。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>spa 测试<span class="nt"></title></span>
<span class="nt"><style></span>
<span class="nc">.btn</span> <span class="p">{</span>
<span class="nl">text-align</span><span class="p">:</span> <span class="nb">center</span><span class="p">;</span>
<span class="p">}</span>
<span class="nf">#content</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">20px</span> <span class="nb">auto</span> <span class="m">20px</span> <span class="nb">auto</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="m">#cccccc</span><span class="p">;</span>
<span class="nl">text-align</span><span class="p">:</span> <span class="nb">center</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">50px</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"content"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"btn"</span><span class="nt">></span>
<span class="nt"><button</span> <span class="na">id=</span><span class="s">"prev"</span><span class="nt">></span>上一页<span class="nt"></button></span>
<span class="nt"><button</span> <span class="na">id=</span><span class="s">"next"</span><span class="nt">></span>下一页<span class="nt"></button></span>
<span class="nt"></div></span>
<span class="nt"><script></span>
<span class="kd">var</span> <span class="nx">page</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">content</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">content</span><span class="dl">'</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">prev</span><span class="dl">'</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">history</span><span class="p">.</span><span class="nx">back</span><span class="p">();</span>
<span class="p">});</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">next</span><span class="dl">'</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">page</span><span class="o">++</span><span class="p">;</span>
<span class="nx">location</span><span class="p">.</span><span class="nx">hash</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">#</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">page</span><span class="p">;</span>
<span class="p">});</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">hashchange</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">hash</span> <span class="o">=</span> <span class="nx">location</span><span class="p">.</span><span class="nx">hash</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">page</span> <span class="o">=</span> <span class="nb">Number</span><span class="p">(</span><span class="nx">hash</span><span class="p">)</span> <span class="o">||</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">content</span><span class="p">.</span><span class="nx">innerText</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">页面</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">hash</span><span class="p">;</span>
<span class="p">});</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<h3 id="history方式">history方式</h3>
<p>此种方式会直接更改掉地址栏的url路径,当在地址栏刷新页面时,会直接发送请求到后台,此时如果后台不存在由<code class="language-plaintext highlighter-rouge">history API</code>生成的url时,将返回404页面,所以要使用这种方式实现<code class="language-plaintext highlighter-rouge">SPA</code>路由,必须要后端配合。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script></span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">next</span><span class="dl">'</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">page</span><span class="o">++</span><span class="p">;</span>
<span class="nx">content</span><span class="p">.</span><span class="nx">innerText</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">页面</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">page</span><span class="p">;</span>
<span class="c1">// pushState和replaceState不会触发popstate事件,只有使用history API后退和前进操作,或者用户在地址栏前进/后退才会触发popstate</span>
<span class="nx">history</span><span class="p">.</span><span class="nx">pushState</span><span class="p">({</span> <span class="na">page</span><span class="p">:</span> <span class="nx">page</span> <span class="p">},</span> <span class="dl">''</span><span class="p">,</span> <span class="dl">'</span><span class="s1">/</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">page</span><span class="p">);</span>
<span class="p">});</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">popstate</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">state</span> <span class="o">=</span> <span class="nx">e</span><span class="p">.</span><span class="nx">state</span> <span class="o">||</span> <span class="p">{};</span>
<span class="nx">page</span> <span class="o">=</span> <span class="nx">state</span><span class="p">.</span><span class="nx">page</span> <span class="o">||</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">content</span><span class="p">.</span><span class="nx">innerText</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">页面</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">state</span><span class="p">.</span><span class="nx">page</span><span class="p">;</span>
<span class="p">});</span>
<span class="nt"></script></span>
</code></pre></div></div>
git子模块
2021-09-23T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2021/09/23/git子模块
<h3 id="添加子模块">添加子模块</h3>
<p><code class="language-plaintext highlighter-rouge">git submodule add <子模块链接> <子模块名称></code></p>
<p>子模块名称就是本地路径</p>
<p><strong>注意:如果github博客里使用了子模块,子模块链接必须使用<code class="language-plaintext highlighter-rouge">web URL</code>,否则将不能构建</strong></p>
<h3 id="初始化子模块">初始化子模块</h3>
<p><code class="language-plaintext highlighter-rouge">git submodeule init</code></p>
<p>对应新<code class="language-plaintext highlighter-rouge">clone</code>的项目,如果其中有子模块,需要使用该命令初始化子模块。</p>
<h3 id="更新子模块">更新子模块</h3>
<p><code class="language-plaintext highlighter-rouge">git submodule update</code>:初始化后首次更新远程代码到本地。
<code class="language-plaintext highlighter-rouge">git submodule update --remote</code>:将远程子模块最新代码更新到本地。</p>
<h3 id="删除子模块">删除子模块</h3>
<ol>
<li>手动删除<code class="language-plaintext highlighter-rouge">config</code>、<code class="language-plaintext highlighter-rouge">.gitmodules</code>中对应的配置</li>
<li>手动删除<code class="language-plaintext highlighter-rouge">.git/modules</code>下对应的目录</li>
<li><code class="language-plaintext highlighter-rouge">git rm -r --cached <子模块名称></code> 清除缓存</li>
</ol>
深入理解vertical-align
2021-09-22T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2021/09/22/深入理解vertical-align
<h3 id="术语">术语</h3>
<ul>
<li>
<p>非替换元素:如果元素的内容包含在文档中,则称之为非替换元素。</p>
</li>
<li>
<p>替换元素:指作为其他内容占位符的一个元素(<code class="language-plaintext highlighter-rouge"><img></code>、<code class="language-plaintext highlighter-rouge"><video></code>、<code class="language-plaintext highlighter-rouge"><audio></code>等)。但,<code class="language-plaintext highlighter-rouge">inline-block</code>元素在布局中也当作替换元素处理。所以,又包含大量的表单类元素及表格类元素。</p>
</li>
<li>
<p>em框 :em框在字体中定义,也称为字符框(character box)。实际的字形可能比其em框更高或更矮。在CSS中,<code class="language-plaintext highlighter-rouge">font-size</code>的值确定了各个em框的高度。</p>
</li>
<li>
<p>内容区:在非替换元素中,内容区是元素中各字符的em框串在一起构成的框;而在替换元素中,内容区就是元素的固有高度再加上可能有的外边距、边框或内边距。内容区类似于一个块级元素的内容框(<code class="language-plaintext highlighter-rouge">content box</code>)。</p>
</li>
<li>
<p>行间距:行间距(leading)是font-size和line-height之差。这个差实际上要分为两半,分别应用到内容区的顶部和底部(注意:行间距只应用于非替换元素)。</p>
</li>
<li>
<p>行内框:行内框通过向内容区增加行间距来描述。对于非替换元素,元素行内框的高度等于<code class="language-plaintext highlighter-rouge">line-height</code>的高度;对于替换元素,元素行内框的高度则恰好等于内容区的高度,因为行间距不应用到替换元素(注意:行内框的区域与内联元素背景颜色所在的区域无关)。</p>
</li>
<li>
<p>行框:行框是包含该行中出现的行内框的最高点和最低点的最小框。换句话说,行框的上边界要位于最高行内框的上边界;而行框的底边要放在最低行内框的下边界。</p>
</li>
</ul>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/line-box.jpg" alt="" /></p>
<h3 id="baseline">baseline</h3>
<p>字母x的下边缘(线)就是基线,默认情况下,行内框的<code class="language-plaintext highlighter-rouge">baseline</code>都与行框的<code class="language-plaintext highlighter-rouge">baseline</code>对齐。</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/baseline.png" alt="" /></p>
<p><code class="language-plaintext highlighter-rouge">baseline</code>的确定规则:</p>
<ul>
<li>
<p><code class="language-plaintext highlighter-rouge">inline-table</code>元素的<code class="language-plaintext highlighter-rouge">baseline</code>是它的<code class="language-plaintext highlighter-rouge">table</code>第一行的<code class="language-plaintext highlighter-rouge">baseline</code>。</p>
</li>
<li>
<p>父元素(<code class="language-plaintext highlighter-rouge">line box</code>)的<code class="language-plaintext highlighter-rouge">baseline</code>是最后一个行内框(<code class="language-plaintext highlighter-rouge">inline box</code>)的<code class="language-plaintext highlighter-rouge">baseline</code>。</p>
</li>
<li>
<p><code class="language-plaintext highlighter-rouge">inline-block</code>元素的<code class="language-plaintext highlighter-rouge">baseline</code>确定规则:</p>
<ul>
<li>
<p>规则1:<code class="language-plaintext highlighter-rouge">inline-block</code>元素,如果内部有<code class="language-plaintext highlighter-rouge">line box</code>,则<code class="language-plaintext highlighter-rouge">inline-block</code>元素的<code class="language-plaintext highlighter-rouge">baseline</code>就是最后一个作为内容存在的元素[inline box]的<code class="language-plaintext highlighter-rouge">baseline</code>,而这个元素的<code class="language-plaintext highlighter-rouge">baseline</code>的确定就要根据它自身来定了。</p>
</li>
<li>
<p>规则2:<code class="language-plaintext highlighter-rouge">inline-block</code>元素,如果其内部没有<code class="language-plaintext highlighter-rouge">line box</code>或它的<code class="language-plaintext highlighter-rouge">overflow</code>属性不是<code class="language-plaintext highlighter-rouge">visible</code>,那么<code class="language-plaintext highlighter-rouge">baseline</code>将是这个<code class="language-plaintext highlighter-rouge">inline-block</code>元素的底<code class="language-plaintext highlighter-rouge">margin</code>边界。具体情况如下所示:</p>
</li>
</ul>
</li>
</ul>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><style></span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">bottom</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.wrap</span> <span class="p">{</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">gold</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#ffffff</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.wrap</span> <span class="nt">span</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.div1</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">10px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"overflow:hidden"</span><span class="nt">></span>
<span class="nt"><span></span>x<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span><span class="nt">></span>
<span class="nt"><span></span>x<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"><span></span>x<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-baseline.png" alt="" /></p>
<h3 id="ie7及以下浏览器中的baseline">ie7及以下浏览器中的baseline</h3>
<p>inline-block元素的baseline确定规则:</p>
<ul>
<li>规则1:<code class="language-plaintext highlighter-rouge">inline-block</code>元素,如果内部有<code class="language-plaintext highlighter-rouge">line box</code>,则假设该元素内部存在一个看不见的相对于该元素绝对定位的文本节点,该文本节点的bottom位置为父元素的<code class="language-plaintext highlighter-rouge">margin-bottom</code>,该文本节点的<code class="language-plaintext highlighter-rouge">baseline</code>即为父元素的<code class="language-plaintext highlighter-rouge">baseline</code>。</li>
<li>规则2:<code class="language-plaintext highlighter-rouge">inline-block</code>元素,如果其内部没有<code class="language-plaintext highlighter-rouge">line box</code>,那么<code class="language-plaintext highlighter-rouge">baseline</code>将是这个<code class="language-plaintext highlighter-rouge">inline-block</code>元素的底<code class="language-plaintext highlighter-rouge">margin</code>边界。具体情况如下所示:</li>
</ul>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><style></span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">bottom</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.wrap</span> <span class="p">{</span>
<span class="nl">margin-top</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">gold</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">50px</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#ffffff</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.wrap</span> <span class="nt">span</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="py">zoom</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.div1</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="err">*</span><span class="nl">display</span><span class="p">:</span> <span class="nb">inline</span><span class="p">;</span>
<span class="err">*</span><span class="py">zoom</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">10px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.line</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
<span class="nl">left</span><span class="p">:</span> <span class="m">-10px</span><span class="p">;</span>
<span class="nl">bottom</span><span class="p">:</span> <span class="m">-20px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">850px</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">border-top</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.anchor</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
<span class="nl">bottom</span><span class="p">:</span> <span class="m">-20px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"z-index:1;"</span><span class="nt">></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>x<span class="nt"></span></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"overflow:hidden"</span><span class="nt">></span>
<span class="nt"><span></span>x<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"anchor"</span><span class="nt">></span>x<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"><span></span>x<span class="nt"></span></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"line-height:150px;"</span><span class="nt">></span>
<span class="nt"><span></span>x<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"anchor"</span><span class="nt">></span>x<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-baseline-ie.png" alt="" /></p>
<h3 id="vertical-alignmiddle">vertical-align:middle</h3>
<p>将元素盒子的垂直中点(不再考虑盒子的<code class="language-plaintext highlighter-rouge">baseline</code>)与父盒子的<code class="language-plaintext highlighter-rouge">baseline</code>加上父盒子的<code class="language-plaintext highlighter-rouge">x-height</code>的一半位置对齐。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><style></span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">bottom</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.wrap</span> <span class="p">{</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">gold</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#ffffff</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.wrap</span> <span class="nt">span</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.div1</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">10px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.div2</span> <span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">50%</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="nl">text-align</span><span class="p">:</span> <span class="nb">right</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.line</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
<span class="nl">top</span><span class="p">:</span> <span class="m">50%</span><span class="p">;</span>
<span class="nl">border-top</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="no">blue</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">300px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:middle"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>xhj<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"font-size:100px;"</span><span class="nt">></span>xhj<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-middle.png" alt="" /></p>
<h3 id="vertical-aligntop">vertical-align:top</h3>
<p>将盒子的顶端(<code class="language-plaintext highlighter-rouge">margin-top</code>边界)与父盒子的内容框顶端对齐。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:top"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>xhj<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"child"</span> <span class="na">style=</span><span class="s">"font-size:100px;"</span><span class="nt">></span>xhj<span class="nt"></span></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-top.png" alt="" /></p>
<p>结果解释:由于<code class="language-plaintext highlighter-rouge">.wrap</code>的<code class="language-plaintext highlighter-rouge">line-height</code>为<code class="language-plaintext highlighter-rouge">100px</code>,而<code class="language-plaintext highlighter-rouge">.child</code>的默认行高大于<code class="language-plaintext highlighter-rouge">100px</code>,因此其顶部将被有一部分溢出容器。</p>
<h3 id="vertical-aligntext-top">vertical-align:text-top</h3>
<p>将盒子的顶端(<code class="language-plaintext highlighter-rouge">margin-top</code>边界)与父盒子的<code class="language-plaintext highlighter-rouge">em</code>框顶端对齐。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:text-top"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>xhj<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"child"</span> <span class="na">style=</span><span class="s">"font-size:100px;"</span><span class="nt">></span>xhj<span class="nt"></span></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-text-top.png" alt="" /></p>
<h3 id="vertical-alignbottom">vertical-align:bottom</h3>
<p>将盒子的顶端(<code class="language-plaintext highlighter-rouge">margin-bottom</code>边界)与父盒子的内容框底端对齐。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:bottom"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>xhj<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"child"</span> <span class="na">style=</span><span class="s">"font-size:100px;"</span><span class="nt">></span>xhj<span class="nt"></span></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-bottom.png" alt="" /></p>
<h3 id="vertical-aligntext-bottom">vertical-align:text-bottom</h3>
<p>将盒子的底端(<code class="language-plaintext highlighter-rouge">margin-bottom</code>边界)与父盒子的<code class="language-plaintext highlighter-rouge">em</code>框底端对齐。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:text-bottom"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>xhj<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"child"</span> <span class="na">style=</span><span class="s">"font-size:100px;"</span><span class="nt">></span>xhj<span class="nt"></span></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-text-bottom.png" alt="" /></p>
<h3 id="vertical-alignsub">vertical-align:sub</h3>
<p>将子元素盒子的<code class="language-plaintext highlighter-rouge">baseline</code>降低,到适当的父盒子的下标位置,类似于<code class="language-plaintext highlighter-rouge"><sub></code>标签的效果。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:sub"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></span>xhj<span class="nt"></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>xhj<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"child"</span> <span class="na">style=</span><span class="s">"font-size:100px;"</span><span class="nt">></span>xhj<span class="nt"></span></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-sub.png" alt="" /></p>
<p>可以看到 div2 中的 xhj 要略微低于右侧 xhj</p>
<h3 id="vertical-alignsuper">vertical-align:super</h3>
<p>将子元素盒子的<code class="language-plaintext highlighter-rouge">baseline</code>升高,到适当的父盒子的上标位置,类似于<code class="language-plaintext highlighter-rouge"><super></code>标签的效果。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:super"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></span>xhj<span class="nt"></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>xhj<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"child"</span> <span class="na">style=</span><span class="s">"font-size:100px;"</span><span class="nt">></span>xhj<span class="nt"></span></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-super.png" alt="" /></p>
<h3 id="vertical-alignpercentage">vertical-align:percentage</h3>
<p>升高(正值)或降低(负值)子元素盒子,具体的升高/降低数值由子盒子的<code class="language-plaintext highlighter-rouge">line-height的</code>乘以百分比计算得出。如果百分比为0%,就和<code class="language-plaintext highlighter-rouge">vertical-align:baseline</code>一样。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"wrap"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:50%"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span> <span class="na">style=</span><span class="s">"text-align:right;"</span><span class="nt">></span>xhj<span class="nt"></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span> <span class="na">style=</span><span class="s">"vertical-align:50px"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span> <span class="na">style=</span><span class="s">"text-align:right;"</span><span class="nt">></span>xhj<span class="nt"></div></span>
<span class="nt"><i</span> <span class="na">class=</span><span class="s">"line"</span><span class="nt">></i></span>
<span class="nt"></div></span>
<span class="nt"><span></span>xhj<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"font-size:100px;"</span><span class="nt">></span>xhj<span class="nt"></span></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/深入理解vertical-align/vertical-align-percentage.png" alt="" /></p>
<h3 id="vertical-alignlength">vertical-align:length</h3>
<p>升高(正值)或降低(负值)子元素盒子,如果百分比为0%,就和<code class="language-plaintext highlighter-rouge">vertical-align:baseline</code>一样。效果和<code class="language-plaintext highlighter-rouge">percentage</code>类似,只不过使用国定值。</p>
ie低版本兼容
2021-09-12T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2021/09/12/ie低版本兼容
<h3 id="标准浏览器">标准浏览器</h3>
<ul>
<li>如果其中一个特性值被设置成了<code class="language-plaintext highlighter-rouge">scroll</code>或<code class="language-plaintext highlighter-rouge">auto’,而另一个特性指定值为</code>visible<code class="language-plaintext highlighter-rouge">,那么</code>visible<code class="language-plaintext highlighter-rouge">会被设置成</code>auto`。</li>
</ul>
<h3 id="ie8及以下浏览器">ie8及以下浏览器</h3>
<ul>
<li>不支持<code class="language-plaintext highlighter-rouge">opacity</code>,可用<code class="language-plaintext highlighter-rouge">filter: alpha(opacity: 100)</code>来代替。</li>
<li>不支持<code class="language-plaintext highlighter-rouge">::before</code>,<code class="language-plaintext highlighter-rouge">::after</code>的标准写法,只支持<code class="language-plaintext highlighter-rouge">:before</code>,<code class="language-plaintext highlighter-rouge">:after</code>。</li>
<li>不支持<code class="language-plaintext highlighter-rouge">:last-child</code>伪类。</li>
<li>当一个元素的<code class="language-plaintext highlighter-rouge">overflow-x</code>或<code class="language-plaintext highlighter-rouge">overflow-y</code>指定值为<code class="language-plaintext highlighter-rouge">hidden</code>,另一个特性的指定值为<code class="language-plaintext highlighter-rouge">visible</code>时,<code class="language-plaintext highlighter-rouge">visible</code>在 IE6 IE7 IE8 中会被设置成<code class="language-plaintext highlighter-rouge">hidden</code>,其它浏览器设置成<code class="language-plaintext highlighter-rouge">auto</code>。</li>
</ul>
<h3 id="ie7及以下浏览器">ie7及以下浏览器</h3>
<ul>
<li>不支持<code class="language-plaintext highlighter-rouge">:before</code>,<code class="language-plaintext highlighter-rouge">:after</code>伪类。</li>
<li>触发<code class="language-plaintext highlighter-rouge">haslayout</code>可以清除内部浮动。</li>
<li>不支持<code class="language-plaintext highlighter-rouge">box-siziong</code>,<code class="language-plaintext highlighter-rouge">ie7</code>默认为<code class="language-plaintext highlighter-rouge">content-box</code>布局,<code class="language-plaintext highlighter-rouge">ie6</code>及以下浏览器默认为<code class="language-plaintext highlighter-rouge">border-box</code>布局。</li>
<li><code class="language-plaintext highlighter-rouge">position:absolute</code>的父元素必须拥有<code class="language-plaintext highlighter-rouge">haslayout</code>,否则其定位将不准确,且会影响兄弟元素的布局。</li>
<li>当<code class="language-plaintext highlighter-rouge">form</code>元素中有内容时,其默认有<code class="language-plaintext highlighter-rouge">20px</code>外边距。</li>
<li>由于幽灵节点的影响,<code class="language-plaintext highlighter-rouge">input</code>基线对齐幽灵节点后,导致其默认有<code class="language-plaintext highlighter-rouge">1px</code>的外边距,可通过使input浮动或者设置其<code class="language-plaintext highlighter-rouge">vertical-align</code>消除。</li>
<li>当元素获得<code class="language-plaintext highlighter-rouge">haslayout</code>后,即使元素内部没有内容,其也会有一个的默认行高撑起其高度,其高度为字体大小加<code class="language-plaintext highlighter-rouge">2px</code>,当<code class="language-plaintext highlighter-rouge">font-size</code>为<code class="language-plaintext highlighter-rouge">0</code>时,其行高为<code class="language-plaintext highlighter-rouge">2px</code>。由于<strong>ie6</strong>高度属性的特性,设置<code class="language-plaintext highlighter-rouge">height:0</code>只会让元素获得<code class="language-plaintext highlighter-rouge">haslayout</code>,而不会有其他效果。让元素获得<code class="language-plaintext highlighter-rouge">haslayout</code>的样式有:
<ul>
<li><code class="language-plaintext highlighter-rouge">zoom</code>不为<code class="language-plaintext highlighter-rouge">0</code>;</li>
<li><code class="language-plaintext highlighter-rouge">float</code>不为<code class="language-plaintext highlighter-rouge">none</code></li>
<li><code class="language-plaintext highlighter-rouge">height</code>不为<code class="language-plaintext highlighter-rouge">auto</code>(<strong>ie7</strong>中,内联元素<code class="language-plaintext highlighter-rouge">height</code>无效)</li>
<li><code class="language-plaintext highlighter-rouge">width</code>不为<code class="language-plaintext highlighter-rouge">auto</code>(<strong>ie7</strong>中,内联元素<code class="language-plaintext highlighter-rouge">width</code>无效)</li>
<li><code class="language-plaintext highlighter-rouge">display:inline-block</code></li>
<li><code class="language-plaintext highlighter-rouge">position:absolute,fixed</code>(注意<strong>ie6</strong>不支持<code class="language-plaintext highlighter-rouge">fixed</code>)</li>
<li><code class="language-plaintext highlighter-rouge">overflow</code>|<code class="language-plaintext highlighter-rouge">overflow-x</code>|<code class="language-plaintext highlighter-rouge">overflow-y</code>不为<code class="language-plaintext highlighter-rouge">visible</code>(<strong>ie7</strong>)</li>
<li><code class="language-plaintext highlighter-rouge">min-height</code>(<strong>ie7</strong>)</li>
<li><code class="language-plaintext highlighter-rouge">min-width</code>(<strong>ie7</strong>)</li>
<li><code class="language-plaintext highlighter-rouge">max-height</code>不为<code class="language-plaintext highlighter-rouge">none</code>(<strong>ie7</strong>)</li>
<li><code class="language-plaintext highlighter-rouge">max-width</code>不为<code class="language-plaintext highlighter-rouge">none</code>(<strong>ie7</strong>)</li>
</ul>
</li>
<li>除了<code class="language-plaintext highlighter-rouge">display:inline-block</code>触发的<code class="language-plaintext highlighter-rouge">haslayout</code>无法重置外,其他方式触发的<code class="language-plaintext highlighter-rouge">haslayout</code>都可以通过重新设置默认值(在其他规则中用默认值覆盖)使其取消<code class="language-plaintext highlighter-rouge">haslayout</code>。</li>
<li>给<code class="language-plaintext highlighter-rouge">block</code>元素添加样式<code class="language-plaintext highlighter-rouge">display:inline-block</code>,只是触发<code class="language-plaintext highlighter-rouge">haslayout</code>,和<code class="language-plaintext highlighter-rouge">zoom:1</code>的效果相同。</li>
<li>没有<code class="language-plaintext highlighter-rouge">haslayout</code>的元素的<code class="language-plaintext highlighter-rouge">clientWidth/clientHeight</code>属性总是返回<code class="language-plaintext highlighter-rouge">0</code>。</li>
<li>当脱离文档流的元素(浮动、绝对定位),内联块元素(<code class="language-plaintext highlighter-rouge">inline-block</code>元素,<code class="language-plaintext highlighter-rouge">block</code>元素在<strong>ie7</strong>以下浏览器中需用<code class="language-plaintext highlighter-rouge">display:inline;zoom:1</code>触发)没有设置宽度时,这时内部子代元素设置百分比宽度后:
<ul>
<li>现代浏览器将按照父元素的实际内部宽度去乘以百分比得出子元素的宽度;</li>
<li><strong>ie7</strong>将忽略百分比宽度,只是触发<code class="language-plaintext highlighter-rouge">haslayout</code>,使其表现为<code class="language-plaintext highlighter-rouge">inline-block</code>;</li>
<li><strong>ie6</strong>浏览器中,如果祖先元素有设置最小宽度(<strong>ie6</strong>中,width相当于min-width),则其表现和<strong>ie7</strong>一致,否则将会向上找到可设置百分比宽度的父元素,将其宽度设置为该百分比宽度,再来设置子元素的宽度,具体情况如<a href="#test1">【示例1】</a>所示。</li>
</ul>
</li>
<li>当脱离文档流的元素,内联块元素没有设置宽度时,这时内部子代元素触发<code class="language-plaintext highlighter-rouge">haslayout</code>后:
<ul>
<li><strong>ie7</strong>中子代元素将表现为<code class="language-plaintext highlighter-rouge">inline-block</code>;</li>
<li><strong>ie6</strong>浏览器中,如果祖先元素有设置最小宽度,则其表现和<strong>ie7</strong>一致,否则如果子代元素是<code class="language-plaintext highlighter-rouge">block</code>元素(包括内联元素通过<code class="language-plaintext highlighter-rouge">display:block</code>形成的块元素),则其相当于设置了<code class="language-plaintext highlighter-rouge">width:100%</code>,表现如上所述;</li>
</ul>
</li>
<li>当元素设置了<code class="language-plaintext highlighter-rouge">position:relative</code>,且没有<code class="language-plaintext highlighter-rouge">haslayout</code>,此时元素顶部半行距高度的背景色将缺失(子元素背景色也受此影响),具体情况如<a href="#test2">【示例2】</a>所示。</li>
<li><code class="language-plaintext highlighter-rouge">li</code>元素即使设置<code class="language-plaintext highlighter-rouge">line-height</code>为0,里面的文字内容还是可以看到,只是文字会冲破容器。</li>
<li><code class="language-plaintext highlighter-rouge">table-layout:fixed</code>将使<code class="language-plaintext highlighter-rouge">table</code>宽度伸展为<code class="language-plaintext highlighter-rouge">100%</code>。</li>
<li>当脱离文档流的元素,内联块元素内部存在空白的没有haslayout的元素时(或者普通元素设置了vertical-align)(注:html注释节点和display:none的节点也会形成空白的没有haslayout的元素),这时元素的最小高度由其<code class="language-plaintext highlighter-rouge">font-size</code>(跟<code class="language-plaintext highlighter-rouge">line-height</code>无关)决定,具体情况如<a href="#test5">【示例5】</a>所示。</li>
</ul>
<h3 id="ie7浏览器">ie7浏览器</h3>
<ul>
<li>当父元素设置了<code class="language-plaintext highlighter-rouge">overflow</code>(<code class="language-plaintext highlighter-rouge">overflow-x</code>,<code class="language-plaintext highlighter-rouge">overflow-y</code>)为<code class="language-plaintext highlighter-rouge">auto</code>或者<code class="language-plaintext highlighter-rouge">hidden</code>,此时如果子元素设置了<code class="language-plaintext highlighter-rouge">position:relative</code>,父元素的overflow将失效,解决方法为给元素也加上<code class="language-plaintext highlighter-rouge">position:relative</code>。具体情况如<a href="#test6">【示例6】</a></li>
<li>当父元素的高度是通过同时设置<code class="language-plaintext highlighter-rouge">top</code>和<code class="language-plaintext highlighter-rouge">bottom</code>获得的时候,子元素设置百分比高度将失效。具体情况如<a href="#test7">【示例7】</a></li>
</ul>
<h3 id="ie6浏览器">ie6浏览器</h3>
<ul>
<li>不支持<code class="language-plaintext highlighter-rouge">:first-child</code>伪类。</li>
<li>不支持<code class="language-plaintext highlighter-rouge">max-width</code>,<code class="language-plaintext highlighter-rouge">max-height</code>。</li>
<li>不支持<code class="language-plaintext highlighter-rouge">min-width</code>,<code class="language-plaintext highlighter-rouge">min-height</code>,不过给元素定义<code class="language-plaintext highlighter-rouge">width</code>和<code class="language-plaintext highlighter-rouge">height</code>后,其表现和<code class="language-plaintext highlighter-rouge">min-width</code>、<code class="language-plaintext highlighter-rouge">min-height</code>一致。根据这一特性,可以给脱离文档流的父元素或者内联块父元素设置一个较小的<code class="language-plaintext highlighter-rouge">width</code>,防止内部子代元素触发<code class="language-plaintext highlighter-rouge">haslayout</code>,撑破父元素,使父元素占满窗口。</li>
<li>不支持同时设置<code class="language-plaintext highlighter-rouge">top,bottom</code>,或者<code class="language-plaintext highlighter-rouge">left,right</code>。</li>
<li>当父元素未设置高度时,子元素设置百分比高度将无效。</li>
<li>并列类名不会增加优先级。</li>
<li>子代元素<code class="language-plaintext highlighter-rouge">absolute</code>定位后,<code class="language-plaintext highlighter-rouge">relative</code>的父元素如果没有触发<code class="language-plaintext highlighter-rouge">haslayout</code>,则子代元素的left:0的位置将对应于父元素的<code class="language-plaintext highlighter-rouge">padding-left</code>的位置。</li>
<li>子代元素<code class="language-plaintext highlighter-rouge">absolute</code>定位后,<code class="language-plaintext highlighter-rouge">relative</code>的父元素如果没有触发<code class="language-plaintext highlighter-rouge">haslayout</code>,则子代元素的bottom:0的位置将对应于距离父元素往下一个窗口高度的位置。</li>
<li>当<code class="language-plaintext highlighter-rouge">li</code>元素<code class="language-plaintext highlighter-rouge">position:relative</code>后,且没有haslayout,其子元素相对其绝对定位后,<code class="language-plaintext highlighter-rouge">li</code>元素在其尾部会多出一个看不见的inline-block节点,导致<code class="language-plaintext highlighter-rouge">li</code>元素高度增加,这种情况可以给<code class="language-plaintext highlighter-rouge">li</code>添加<code class="language-plaintext highlighter-rouge">zoom:1</code>来解决。当<code class="language-plaintext highlighter-rouge">li</code>获得<code class="language-plaintext highlighter-rouge">haslayout</code>后,子元素绝对定位或者浮动后,<code class="language-plaintext highlighter-rouge">li</code>元素下面会多出4px的边距(这个bug,ie7也有),对于这种情况,可以个<code class="language-plaintext highlighter-rouge">li</code>标签添加<code class="language-plaintext highlighter-rouge">vertical-align:top|middle|bottom</code>解决。具体情况如<a href="#test3">【示例3】</a>。</li>
<li>当haslayout元素<code class="language-plaintext highlighter-rouge">position:relative</code>后,此时如果子元素浮动后且设置了宽度100%,其相邻的绝对定位的兄弟元素将消失不见。对于这种情况,可以添加一个空白节点解决。具体情况如<a href="#test4">【示例4】</a>。</li>
<li><code class="language-plaintext highlighter-rouge">iframe</code>中的<code class="language-plaintext highlighter-rouge">body</code>标签必须加<code class="language-plaintext highlighter-rouge">overflow:auto,hidden</code>样式,否则其默认有一个看不见的垂直滚动条,导致页面内容宽度减少了<code class="language-plaintext highlighter-rouge">17px</code>。具体情况如<a href="#test8">【示例8】</a>所示。</li>
</ul>
<h3 id="ie-css-hack">ie css hack</h3>
<ul>
<li>属性名称前加<code class="language-plaintext highlighter-rouge">*</code>,<strong>ie6</strong>和<strong>ie7</strong>都支持该写法</li>
<li>属性名称前加<code class="language-plaintext highlighter-rouge">_</code>,<strong>ie6</strong>支持</li>
<li>规则前面加<code class="language-plaintext highlighter-rouge">*+html </code>,<strong>ie7</strong>支持</li>
<li><strong>ie6</strong>不支持<code class="language-plaintext highlighter-rouge">!important</code></li>
<li>属性值后面加<code class="language-plaintext highlighter-rouge">\0/</code>,<strong>ie8</strong>支持</li>
<li><strong>ie7</strong>及以上浏览器支持<code class="language-plaintext highlighter-rouge">+</code>选择器</li>
</ul>
<p><a href="https://blog.lisong.hn.cn//code/%E5%85%B6%E4%BB%96/layout/layout.html">haslayout 触发方式详细列表</a></p>
<p>以下元素,默认具有<code class="language-plaintext highlighter-rouge">haslayout</code>:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge"><html></code>, <code class="language-plaintext highlighter-rouge"><body></code></li>
<li><code class="language-plaintext highlighter-rouge"><table></code>, <code class="language-plaintext highlighter-rouge"><tr></code>, <code class="language-plaintext highlighter-rouge"><th></code>, <code class="language-plaintext highlighter-rouge"><td></code></li>
<li><code class="language-plaintext highlighter-rouge"><img></code></li>
<li><code class="language-plaintext highlighter-rouge"><hr></code></li>
<li><code class="language-plaintext highlighter-rouge"><input></code>, <code class="language-plaintext highlighter-rouge"><button></code>, <code class="language-plaintext highlighter-rouge"><select></code>, <code class="language-plaintext highlighter-rouge"><textarea></code>, <code class="language-plaintext highlighter-rouge"><fieldset></code>, <code class="language-plaintext highlighter-rouge"><legend></code></li>
<li><code class="language-plaintext highlighter-rouge"><iframe></code>, <code class="language-plaintext highlighter-rouge"><embed></code>, <code class="language-plaintext highlighter-rouge"><object></code>, <code class="language-plaintext highlighter-rouge"><applet></code></li>
<li><code class="language-plaintext highlighter-rouge"><marquee></code></li>
</ul>
<p><a name="test1">示例1:</a></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:relative;color:#fff;white-space:nowrap;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:absolute;background:red;"</span><span class="nt">></span>
<span class="nt"><div></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"test1"</span> <span class="na">style=</span><span class="s">"width:50%;background:blue;"</span><span class="nt">></span>哈哈哈哈<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"test2"</span> <span class="na">style=</span><span class="s">"background:green;"</span><span class="nt">></span>哈哈哈哈哈<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><strong>ie6</strong>中结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/1-1.png" alt="" /></p>
<p><strong>ie7</strong>中结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/1-2.png" alt="" /></p>
<p>现代浏览器中结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/1-3.png" alt="" /></p>
<p><strong>ie6</strong>中,当给祖先元素设置宽度后:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:relative;color:#fff;white-space:nowrap;width:10px;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:absolute;background:red;"</span><span class="nt">></span>
<span class="nt"><div></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"test1"</span> <span class="na">style=</span><span class="s">"width:50%;background:blue;"</span><span class="nt">></span>哈哈哈哈<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"test2"</span> <span class="na">style=</span><span class="s">"background:green;"</span><span class="nt">></span>哈哈哈哈哈<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p><strong>ie6</strong>中结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/1-2.png" alt="" /></p>
<p><a name="test2">示例2:</a></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:absolute;background:red;line-height:100px;color:#fff;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"test1"</span> <span class="na">style=</span><span class="s">"background:blue;position:relative;"</span><span class="nt">></span>哈哈哈<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><strong>ie6</strong>,<strong>ie7</strong>中结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/2-1.png" alt="" /></p>
<p><a name="test3">示例3:</a></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><style></span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">ul</span><span class="o">,</span><span class="nt">li</span> <span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">list-style</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">ul</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">li</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><ul></span>
<span class="nt"><li></span>
<span class="nt"><div></span>按钮<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:absolute;top:0;right:0;"</span><span class="nt">></div></span>
<span class="nt"></li></span>
<span class="nt"></ul></span>
<span class="nt"><ul</span> <span class="na">style=</span><span class="s">"margin-top: 10px;"</span><span class="nt">></span>
<span class="nt"><li></span>
<span class="nt"><div></span>按钮<span class="nt"></div></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"zoom:1;"</span><span class="nt">></span>test<span class="nt"></span></span>
<span class="nt"></li></span>
<span class="nt"></ul></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>ie6</strong>下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/3-1.png" alt="" /></p>
<p>给<code class="language-plaintext highlighter-rouge">li</code>添加上<code class="language-plaintext highlighter-rouge">zoom:1</code>:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">li</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="py">zoom</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>ie6</strong>,<strong>ie7</strong>下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/3-2.png" alt="" /></p>
<p>给<code class="language-plaintext highlighter-rouge">li</code>添加上<code class="language-plaintext highlighter-rouge">vertical-align:middle</code>:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">li</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="py">zoom</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="nl">vertical-align</span><span class="p">:</span> <span class="nb">middle</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><strong>ie6</strong>,<strong>ie7</strong>下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/3-3.png" alt="" /></p>
<p><a name="test4"><strong>示例4:</strong></a></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:relative;background:red;width:200px;padding:20px;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:absolute;right:0;"</span><span class="nt">></span>test<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">style=</span><span class="s">"float:left;width:100%;background:blue;"</span> <span class="nt">></div></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p><strong>ie6</strong>下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/4-1.png" alt="" /></p>
<p>当添加一个空白元素后:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:relative;background:red;width:200px;padding:20px;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:absolute;right:0;"</span><span class="nt">></span>test<span class="nt"></div></span>
<span class="nt"><div></div></span>
<span class="nt"><div</span> <span class="na">type=</span><span class="s">"text"</span> <span class="na">style=</span><span class="s">"float:left;width:100%;background:blue;"</span> <span class="nt">></div></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p><strong>ie6</strong>下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/4-2.png" alt="" /></p>
<p><a name="test5"><strong>示例5:</strong></a></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><style></span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">bottom</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.warp</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">margin-right</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">50px</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="nl">float</span><span class="p">:</span> <span class="nb">left</span><span class="p">;</span>
<span class="c">/* vertical-align: middle; */</span>
<span class="c">/* *display: inline; */</span>
<span class="c">/* *zoom: 1; */</span>
<span class="c">/* position: absolute; */</span>
<span class="p">}</span>
<span class="nc">.child</span> <span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">36px</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">36px</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">14px</span><span class="p">;</span>
<span class="nl">vertical-align</span><span class="p">:</span> <span class="nb">middle</span><span class="p">;</span><span class="err">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"warp"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"empty"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"child"</span><span class="nt">></span>test<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"warp"</span> <span class="na">style=</span><span class="s">"left:110px"</span><span class="nt">><span</span> <span class="na">style=</span><span class="s">"line-height:normal;"</span><span class="nt">></span>xhj<span class="nt"></span></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>ie6</strong>,<strong>ie7</strong>下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/5-1.png" alt="" /></p>
<p>更改<code class="language-plaintext highlighter-rouge"><div id="empty"></div></code>为如下节点,结果和上图一致:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">class=</span><span class="s">"warp"</span><span class="nt">></span>
<span class="c"><!-- test --></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"child"</span><span class="nt">></span>test<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"warp"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"display:none"</span><span class="nt">></span>test<span class="nt"><div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"child"</span><span class="nt">></span>test<span class="nt"></div></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p>更改<code class="language-plaintext highlighter-rouge">wrap</code>的样式为如下几种,结果和上图一致:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.warp</span> <span class="p">{</span>
<span class="c">/* 省略上半样式 */</span>
<span class="c">/* float: left; */</span>
<span class="c">/* vertical-align: middle; */</span>
<span class="err">*</span><span class="nl">display</span><span class="p">:</span> <span class="nb">inline</span><span class="p">;</span>
<span class="err">*</span><span class="py">zoom</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="c">/* position: absolute; */</span>
<span class="p">}</span>
<span class="nc">.warp</span> <span class="p">{</span>
<span class="c">/* 省略上半样式 */</span>
<span class="c">/* float: left; */</span>
<span class="c">/* vertical-align: middle; */</span>
<span class="c">/* *display: inline; */</span>
<span class="c">/* *zoom: 1; */</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.warp</span> <span class="p">{</span>
<span class="c">/* 省略上半样式 */</span>
<span class="c">/* float: left; */</span>
<span class="nl">vertical-align</span><span class="p">:</span> <span class="nb">middle</span><span class="p">;</span>
<span class="c">/* *display: inline; */</span>
<span class="c">/* *zoom: 1; */</span>
<span class="c">/* position: absolute; */</span>
<span class="p">}</span>
</code></pre></div></div>
<p><a name="test6"><strong>示例6:</strong></a></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">style=</span><span class="s">"width:100px;height:100px;overflow:hidden;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:relative;zoom:1;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background-color:red;height:200px;"</span><span class="nt">></span>test<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p><strong>ie7</strong>下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/6-1.png" alt="" /></p>
<p><a name="test7"><strong>示例7:</strong></a></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:relative;width:100px;height:100px;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"position:absolute;top:0;bottom:0;width:100%;background:red;"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"height:100%;background:blue;"</span><span class="nt">></div></span>
<span class="nt"></div></span>
<span class="nt"></div></span>
</code></pre></div></div>
<p><strong>ie7</strong>下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/7-1.png" alt="" /></p>
<p><a name="test8"><strong>示例8:</strong></a></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><body></span>
<span class="nt"><iframe</span> <span class="na">src=</span><span class="s">"http://192.168.189.1/login.html"</span> <span class="na">frameborder=</span><span class="s">"0"</span> <span class="na">style=</span><span class="s">"width:200px;height:100px;border:1px solid black;"</span><span class="nt">></iframe></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/其他/ie低版本兼容/8-1.png" alt="" /></p>
centos7翻墙
2021-07-03T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2021/07/03/centos7翻墙
<h3 id="一键安装">一键安装</h3>
<p>用root账户登录后(vultr默认是root账户登录),开始安装一键shadowsock脚本:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#命令1:(可双击复制)</span>
wget <span class="nt">--no-check-certificate</span> <span class="nt">-O</span> shadowsocks-libev.sh https://raw.githubusercontent.com/wanls4583/wanls4583.github.io/master/code/shadowsocks/shadowsocks-libev.sh
<span class="c">#命令2:</span>
<span class="nb">chmod</span> +x shadowsocks-libev.sh
<span class="c">#命令3:</span>
./shadowsocks-libev.sh 2>&1 | <span class="nb">tee </span>shadowsocks-libev.log
</code></pre></div></div>
<h3 id="防火墙">防火墙</h3>
<p>执行命令3后按照提示输入连接密码、端口号、加密方法即可完成安装。脚本将自动把输入的端口号添加到防火墙,如果后续需要修改了端口,可用如下命令添加防火墙:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>firewall-cmd <span class="nt">--permanent</span> <span class="nt">--add-port</span><span class="o">=</span>8080/tcp
firewall-cmd <span class="nt">--reload</span>
</code></pre></div></div>
<h3 id="修改配置">修改配置</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>vi /etc/shadowsocks-libev/config.json
<span class="c">#内容如下</span>
<span class="o">{</span>
<span class="s2">"server"</span>:[<span class="s2">"[::0]"</span>,<span class="s2">"0.0.0.0"</span><span class="o">]</span>,
<span class="s2">"server_port"</span>:12620,
<span class="s2">"password"</span>:<span class="s2">"520131"</span>,.
<span class="s2">"timeout"</span>:300,
<span class="s2">"user"</span>:<span class="s2">"nobody"</span>,
<span class="s2">"method"</span>:<span class="s2">"aes-256-gcm"</span>,
<span class="s2">"fast_open"</span>:false,
<span class="s2">"nameserver"</span>:<span class="s2">"1.0.0.1"</span>,
<span class="s2">"mode"</span>:<span class="s2">"tcp_and_udp"</span>
<span class="o">}</span>
</code></pre></div></div>
<p><em>修改后记得重新启动服务</em></p>
<h3 id="相关命令">相关命令</h3>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#启动shadowsock:</span>
/etc/init.d/shadowsocks start
<span class="c">#停止shadowsock:</span>
/etc/init.d/shadowsocks stop
<span class="c">#重启shadowsock:</span>
/etc/init.d/shadowsocks restart
<span class="c">#查看shadowsock状态:</span>
/etc/init.d/shadowsocks status
</code></pre></div></div>
js严格模式
2021-04-06T15:18:00+00:00
https://blog.lisong.hn.cn/javascript/2021/04/06/js严格模式
<blockquote>
<p>“严格模式”体现了Javascript更合理、更安全、更严谨的发展方向,包括IE 10在内的主流浏览器,都已经支持它。</p>
</blockquote>
<p>js严格模式主要有以下好处:</p>
<ul>
<li>消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为;</li>
<li>消除代码运行的一些不安全之处,保证代码运行的安全;</li>
<li>提高编译器效率,增加运行速度;</li>
<li>为未来新版本的Javascript做好铺垫。</li>
</ul>
<h3 id="严格模式有两种调用方法适用于不同的场合">“严格模式”有两种调用方法,适用于不同的场合。</h3>
<p>针对整个脚本:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script></span>
<span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">这是严格模式。</span><span class="dl">"</span><span class="p">);</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>针对单个函数:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">strict</span><span class="p">(){</span>
<span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="k">return</span> <span class="dl">"</span><span class="s2">这是严格模式。</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="语法和行为改变">语法和行为改变</h3>
<h4 id="1全局变量显式声明">1、全局变量显式声明</h4>
<p>在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span>
<span class="nx">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//报错</span>
</code></pre></div></div>
<h4 id="2静态绑定">2、静态绑定</h4>
<ul>
<li>禁止使用with语句(因为with语句无法在编译时就确定,属性到底归属哪个对象)</li>
<li>正常模式下,Javascript语言有两种变量作用域(scope):全局作用域和函数作用域。严格模式创设了第三种作用域:eval作用域。严格模式下,eval语句的作用域,取决于它处于全局作用域,还是处于函数作用域。严格模式下,eval语句本身就是一个作用域,不再能够生成全局变量了,它所生成的变量只能用于eval内部。</li>
</ul>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span>
<span class="nb">eval</span><span class="p">(</span><span class="dl">'</span><span class="s1">var x = 1</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span> <span class="c1">//报错</span>
</code></pre></div></div>
<h4 id="3增强的安全措施">3、增强的安全措施</h4>
<ul>
<li>禁止this关键字指向全局对象</li>
<li>禁止在函数内部遍历调用栈</li>
</ul>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">f</span><span class="p">()</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">arguments</span><span class="p">;</span>
<span class="nx">f1</span><span class="p">.</span><span class="nx">caller</span><span class="p">;</span> <span class="c1">//报错</span>
<span class="nx">f1</span><span class="p">.</span><span class="nx">arguments</span><span class="p">;</span> <span class="c1">//报错</span>
<span class="k">this</span><span class="p">.</span><span class="nx">test</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">//报错</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">();</span>
</code></pre></div></div>
<h4 id="4禁止删除变量">4、禁止删除变量</h4>
<p>严格模式下无法删除变量。只有configurable设置为true的对象属性,才能被删除。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">x</span><span class="p">;</span>
<span class="k">delete</span> <span class="nx">x</span><span class="p">;</span> <span class="c1">// 语法错误</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">x</span><span class="dl">'</span><span class="p">:</span> <span class="p">{</span>
<span class="na">value</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="na">configurable</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="k">delete</span> <span class="nx">o</span><span class="p">.</span><span class="nx">x</span><span class="p">;</span> <span class="c1">// 删除成功</span>
</code></pre></div></div>
<h4 id="5显式报错">5、显式报错</h4>
<ul>
<li>正常模式下,对一个对象的只读属性进行赋值,不会报错,只会默默地失败。严格模式下,将报错。</li>
<li>严格模式下,对一个使用getter方法读取的属性进行赋值,会报错。</li>
<li>严格模式下,对禁止扩展的对象添加新属性,会报错。</li>
<li>严格模式下,删除一个不可删除的属性,会报错。</li>
</ul>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">defineProperty</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="dl">"</span><span class="s2">v</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span>
<span class="na">value</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="na">writable</span><span class="p">:</span> <span class="kc">false</span>
<span class="p">});</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">v</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 报错</span>
<span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="kd">get</span> <span class="nx">v</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">v</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="c1">// 报错</span>
<span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">preventExtensions</span><span class="p">(</span><span class="nx">o</span><span class="p">);</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">v</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="c1">// 报错</span>
<span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="k">delete</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">;</span> <span class="c1">// 报错</span>
</code></pre></div></div>
<h4 id="6重名错误">6、重名错误</h4>
<ul>
<li>对象不能有重名的属性</li>
<li>函数不能有重名的参数</li>
</ul>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">a</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span>
<span class="na">a</span><span class="p">:</span> <span class="mi">2</span>
<span class="p">}</span> <span class="c1">//报错</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">)</span> <span class="p">{</span>
<span class="p">}</span> <span class="c1">//报错</span>
</code></pre></div></div>
<h4 id="7禁止八进制表示法">7、禁止八进制表示法</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">n</span> <span class="o">=</span> <span class="mi">0100</span><span class="p">;</span> <span class="c1">// 语法错误</span>
</code></pre></div></div>
<h4 id="8arguments对象的限制">8、arguments对象的限制</h4>
<p>(1)不允许对arguments赋值</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">arguments</span><span class="o">++</span><span class="p">;</span> <span class="c1">// 语法错误</span>
<span class="kd">function</span> <span class="nx">arguments</span><span class="p">()</span> <span class="p">{</span> <span class="p">}</span> <span class="c1">// 语法错误</span>
</code></pre></div></div>
<p>(2)arguments不再追踪参数的变化</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">a</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">return</span> <span class="p">[</span><span class="nx">a</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">[</span><span class="mi">0</span><span class="p">]];</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//正常模式为[2,2]</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">a</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">return</span> <span class="p">[</span><span class="nx">a</span><span class="p">,</span> <span class="nx">arguments</span><span class="p">[</span><span class="mi">0</span><span class="p">]];</span>
<span class="p">}</span>
<span class="nx">f</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//严格模式为[2,1]</span>
</code></pre></div></div>
<p>(3)禁止使用arguments.callee</p>
<p>这意味着,你无法在匿名函数内部调用自身了。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="dl">"</span><span class="s2">use strict</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">arguments</span><span class="p">.</span><span class="nx">callee</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">f</span><span class="p">();</span> <span class="c1">//报错</span>
</code></pre></div></div>
<h4 id="9函数必须声明在顶层">9、函数必须声明在顶层</h4>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">function</span> <span class="nx">f</span><span class="p">(){};</span> <span class="c1">//报错</span>
<span class="p">}</span>
</code></pre></div></div>
前端面试题
2021-03-15T14:52:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2021/03/15/前端面试题
<h3 id="js作用域">JS作用域</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span><span class="o">=</span><span class="mi">10</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">aaa</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">a</span><span class="o">=</span><span class="mi">20</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">aaa</span><span class="p">();</span> <span class="c1">//undefined</span>
</code></pre></div></div>
<p>解释:<code class="language-plaintext highlighter-rouge">aaa</code>函数里的变量进行了提升,相当于先声明了变量<code class="language-plaintext highlighter-rouge">var a</code>,后面再进行赋值操作。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">aa</span><span class="p">(){</span> <span class="kd">var</span> <span class="nx">a</span><span class="o">=</span><span class="nx">b</span><span class="o">=</span><span class="mi">10</span> <span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">);</span> <span class="c1">//10</span>
</code></pre></div></div>
<p>解释:<code class="language-plaintext highlighter-rouge">var a=b=10</code>,相当于<code class="language-plaintext highlighter-rouge">var a;b=10;a=b;</code>,未声明的b变成了全局变量</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">Foo</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">getName</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span> <span class="p">};</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Foo</span><span class="p">.</span><span class="nx">getName</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span> <span class="p">};</span>
<span class="nx">Foo</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">getName</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">3</span><span class="p">);</span> <span class="p">};</span>
<span class="kd">var</span> <span class="nx">getName</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">4</span><span class="p">);</span> <span class="p">};</span>
<span class="kd">function</span> <span class="nx">getName</span><span class="p">()</span> <span class="p">{</span> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">5</span><span class="p">);</span> <span class="p">}</span>
<span class="c1">//请写出以下输出结果:</span>
<span class="nx">Foo</span><span class="p">.</span><span class="nx">getName</span><span class="p">();</span> <span class="c1">//2</span>
<span class="nx">getName</span><span class="p">();</span> <span class="c1">//4</span>
<span class="nx">Foo</span><span class="p">().</span><span class="nx">getName</span><span class="p">();</span> <span class="c1">//1</span>
<span class="nx">getName</span><span class="p">();</span> <span class="c1">//1</span>
<span class="k">new</span> <span class="nx">Foo</span><span class="p">.</span><span class="nx">getName</span><span class="p">();</span> <span class="c1">//2</span>
<span class="k">new</span> <span class="nx">Foo</span><span class="p">().</span><span class="nx">getName</span><span class="p">();</span> <span class="c1">//3</span>
<span class="k">new</span> <span class="k">new</span> <span class="nx">Foo</span><span class="p">().</span><span class="nx">getName</span><span class="p">();</span><span class="c1">//3</span>
</code></pre></div></div>
<p>解释:</p>
<ul>
<li>第一问,调用<code class="language-plaintext highlighter-rouge">Foo</code>的函数属性getName,直接执行<code class="language-plaintext highlighter-rouge">Foo.getName</code></li>
<li>第二问,最后的函数声明进行了函数提升,所以最被<code class="language-plaintext highlighter-rouge">var getName</code>那一行的函数表达式给覆盖了</li>
<li>第三问,执行<code class="language-plaintext highlighter-rouge">Foo()</code>后重新用函数表达式覆盖了getName函数,最后返回的this相当于window对象</li>
<li>第四问,结果同上</li>
<li>第五问,成员运问符号<code class="language-plaintext highlighter-rouge">.</code>的优先级(18)大于<code class="language-plaintext highlighter-rouge">new</code>无参运算符的优先级(17),因此这一问的代码相当于<code class="language-plaintext highlighter-rouge">new (Foo.getName)()</code></li>
<li>第六问,<code class="language-plaintext highlighter-rouge">new</code>带参运算符优先级(18)等于成员运算符<code class="language-plaintext highlighter-rouge">.</code>的优先级(18),因此这一问的代码相当于<code class="language-plaintext highlighter-rouge">(new Foo()).getName()</code></li>
<li>第七问,根据优先级,这一问的代码相当于<code class="language-plaintext highlighter-rouge">new (new Foo()).getName)()</code></li>
</ul>
<h3 id="js运算符">JS运算符</h3>
<p><strong>运算符优先级总结(从上到下依次递减)</strong></p>
<ul>
<li>()</li>
<li>成员符号., [], new()</li>
<li>new</li>
<li>一元运算符
<ul>
<li>后置++, 后置–</li>
<li>前置++, 前置–, !, ~, 一元加法+, 一元减法-, typeof, void, delete, await</li>
</ul>
</li>
<li>二元运算符
<ul>
<li>**</li>
<li>*, /, %</li>
<li>+, -</li>
<li>>>, <<, >>></li>
<li><, <=, >, >=, in, instanceof</li>
<li>=, !=, ===, !==</li>
<li>&</li>
<li></li>
<li>|</li>
<li>&&</li>
<li>||</li>
<li>??</li>
<li>?:</li>
<li>=</li>
</ul>
</li>
<li>yield, yield*</li>
<li>…</li>
<li>,</li>
</ul>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="o">++-</span><span class="mi">1</span><span class="o">+</span><span class="nx">a</span><span class="p">)</span> <span class="c1">//2</span>
</code></pre></div></div>
<p>解释:第一个<code class="language-plaintext highlighter-rouge">a++</code>返回的值为1,后面一个a返回的值为2,相当于<code class="language-plaintext highlighter-rouge">1-1+2</code></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="o">++</span><span class="nx">a</span><span class="o">-</span><span class="mi">1</span><span class="o">+</span><span class="nx">a</span><span class="p">)</span> <span class="c1">//3</span>
</code></pre></div></div>
<p>解释:第一个<code class="language-plaintext highlighter-rouge">++a</code>返回的值为2,后面一个a返回的值也为2,相当于<code class="language-plaintext highlighter-rouge">2-1+2</code></p>
csrf攻击
2019-09-28T00:00:00+00:00
https://blog.lisong.hn.cn/web%E5%AE%89%E5%85%A8/2019/09/28/csrf攻击
<blockquote>
<p>CSRF(Cross Site Request Forgeries)跨网站请求伪造,也叫XSRF,通过伪装来自受信任用户的请求来攻击利用受信任网站。</p>
</blockquote>
<p><strong>原理:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/web安全/csrf攻击.jpg" alt="" /></p>
<p>例:</p>
<ol>
<li>用户打开浏览器,访问受信任银行网站,输入用户名和密码请求登录网站;</li>
<li>在用户信息通过验证后,银行网站产生Cookie信息并返回给浏览器,此时用户登录网站成功,可以正常发送请求到网站;</li>
<li>用户未退出银行网站之前,在同一浏览器中,打开一个TAB页访问其他网站B;</li>
<li>这时候网站B 已被黑客注入诱导信息,加入是一张图片,图片地址指向src=”http://bank.example/withdraw?account=bob&amount=1000000&for=黑客”,点击之后转账给黑客这个账户;</li>
<li>浏览器在接收到这些攻击性代码请求后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,根据用户的Cookie信息以C的权限处理该请求,导致来自黑客请求恶意代码被执行。</li>
</ol>
<p><strong>CSRF防范:</strong></p>
<p>方法一、Token 验证:(用的最多)</p>
<ul>
<li>服务器发送给客户端一个token</li>
<li>客户端提交的表单中带着这个token</li>
<li>如果这个 token 不合法,那么服务器拒绝这个请求</li>
</ul>
<p>由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。另外使用Token时应注意Token的保密性,尽量把敏感操作由GET改为POST,以form或AJAX形式提交,避免Token泄露。</p>
<p>方法二:隐藏令牌:</p>
<p>把 token 隐藏在 http 的 head头中。该和方法一有点像,本质上没有太大区别,只是使用方式上有区别。</p>
<p>方法三、Referer 验证:</p>
<p>Referer 指的是页面请求来源。意思是,只接受本站的请求,服务器才做响应;如果不是,就拦截(有些低版本浏览器存在Referer被更改的风险,如IE6或FF2)。</p>
js垃圾回收机制
2019-09-08T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/09/08/js垃圾回收机制
<blockquote>
<p>JavaScript引擎常用的垃圾回收机制有两种,一种是标记清除法,一种是引用计数法,有的浏览器会同时使用这两种。</p>
</blockquote>
<h2 id="标记清除法">标记清除法</h2>
<p>标记清除算法从名称上看,可以拆分为两部分:标记(mark)和清除(sweep)。</p>
<p>此算法可以分为两个阶段,一个是标记阶段,一个是清除阶段,下面就分别做一下介绍。</p>
<ul>
<li>标记阶段:</li>
</ul>
<p>在此阶段,垃圾回收器会从mutator(应用程序)根对象开始遍历。每一个可以从根对象访问到的对象都会被添加一个标识,于是这个对象就被标识为可到达对象。</p>
<ul>
<li>清除阶段:</li>
</ul>
<p>在此阶段中,垃圾回收器,会对堆内存从头到尾进行线性遍历,如果发现有对象没有被标识为可到达对象,那么就将此对象占用的内存回收,并且将原来标记为可到达对象的标识清除,以便进行下一次垃圾回收操作。</p>
<p>在使用标记清除算法时,未引用对象并不会被立即回收.取而代之的做法是,垃圾对象将一直累计到内存耗尽为止.当内存耗尽时,程序将会被挂起,垃圾回收开始执行。</p>
<p>特别说明:在垃圾回收阶段,应用程序的执行会暂停,等待回收执行完毕后,再恢复程序的执行。</p>
<h2 id="引用计数">引用计数</h2>
<p>记录每个对象被引用的次数,每次被创建引用的时候加1,有不引用它的就减1,当减到0的时候这个对象就应该被垃圾回收。</p>
<h2 id="引用计数法的弊端">引用计数法的弊端</h2>
<p>环形引用:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">marry</span><span class="p">(</span><span class="nx">man</span><span class="p">,</span> <span class="nx">woman</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">woman</span><span class="p">.</span><span class="nx">husband</span> <span class="o">=</span> <span class="nx">man</span><span class="p">;</span>
<span class="nx">man</span><span class="p">.</span><span class="nx">wife</span> <span class="o">=</span> <span class="nx">woman</span><span class="p">;</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">father</span><span class="p">:</span> <span class="nx">man</span><span class="p">,</span>
<span class="na">mother</span><span class="p">:</span> <span class="nx">woman</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">let</span> <span class="nx">family</span> <span class="o">=</span> <span class="nx">marry</span><span class="p">({</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">John</span><span class="dl">"</span>
<span class="p">},</span> <span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">"</span><span class="s2">Ann</span><span class="dl">"</span>
<span class="p">});</span>
<span class="nx">family</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
</code></pre></div></div>
<p>如果使用的标记清除法,只要中断了这个环与外界的引用,那么整个环都是垃圾;如果是用引用计数法,则会发生内存泄露。</p>
<p>低版本IE(ie9之前)中有一部分对象并不是原生JS对象。例如,其BOM和DOM中的对象就是使用C++以COM(Component Object Model)对象的形式实现的,而COM对象的垃圾收集机制采用的就是引用计数策略。</p>
<p>因此即使IE的js引擎是用的标记清除来实现的,但是js访问COM对象如BOM,DOM还是基于引用计数的策略的,也就是说只要在IE中设计到COM对象,也就会存在循环引用的问题。</p>
<p>IE循环引用典型例子:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">outerFunction</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">eleId</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">innerfunction</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">id</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>由于监听函数innerfunction引用到了obj,从而形成了闭包,导致obj不能被释放,从而形成了循环引用,这时即使把window.onload赋值为null,obj也无法释放,可以改成如下方式,避免内存泄露:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">outerFunction</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">eleId</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">id</span> <span class="o">=</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">id</span><span class="p">;</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">onclick</span> <span class="o">=</span> <span class="kd">function</span> <span class="nx">innerfunction</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">id</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">obj</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
DOMContentLoaded与load事件区别
2019-09-07T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/09/07/DOMContentLoaded与load事件区别
<p>当HTML文档加载并解析完成,并且执行完<strong>同步JS代码</strong>后将会触发DOMContentLoaded事件;当页面上所有的资源(图片,音频,视频等)被加载以后才会触发load事件,其在DOMContentLoaded事件之后。</p>
<p>需要注意的是:<strong>同步JS代码</strong>如果造成了了新的资源加载请求,将会延迟load事件的触发时间。</p>
<p>示例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"></body></span>
<span class="nt"><script></span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">html load</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">DOMContentLoaded</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">DOMContentLoaded</span><span class="dl">"</span><span class="p">);</span>
<span class="p">},</span> <span class="kc">false</span><span class="p">)</span>
<span class="nt"></script></span>
<span class="nt"><script></span>
<span class="kd">var</span> <span class="nx">img</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">img</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">img</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">https://blog.lisong.hn.cn/images/abstract-1.jpg</span><span class="dl">'</span>
<span class="nx">img</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">img load</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">img</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">inner js</span><span class="dl">'</span><span class="p">)</span>
<span class="nt"></script></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"outer.js"</span><span class="nt">></script></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>outer.js:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>console.log('outer js')
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/DOMContentLoaded-load-1.png" alt="" /></p>
<p>因为同步代码形成了新的资源请求,load事件需要等待资源请求完成后再触发</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"></body></span>
<span class="nt"><script></span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">html load</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">DOMContentLoaded</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">DOMContentLoaded</span><span class="dl">"</span><span class="p">);</span>
<span class="p">},</span> <span class="kc">false</span><span class="p">)</span>
<span class="nt"></script></span>
<span class="nt"><script></span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">img</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">img</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">img</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">https://blog.lisong.hn.cn/images/abstract-1.jpg</span><span class="dl">'</span>
<span class="nx">img</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">img load</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">img</span><span class="p">)</span>
<span class="p">},</span> <span class="mi">0</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">inner js</span><span class="dl">'</span><span class="p">)</span>
<span class="nt"></script></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"outer.js"</span><span class="nt">></script></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/DOMContentLoaded-load-2.png" alt="" /></p>
<p>可以看出,<strong>异步JS代码</strong>形成的资源请求对load触发时机没有影响</p>
安卓四大组件学习笔记
2019-08-31T00:00:00+00:00
https://blog.lisong.hn.cn/%E7%A7%BB%E5%8A%A8%E7%AB%AF/2019/08/31/安卓四大组件学习笔记
<blockquote>
<p>安卓四大组件包括:Activity、Service、BroadcastReciever、ContentProvider。这四大组件是安卓应用的核心组件,通过这四个组件可以实现复杂的交互,应用之间的数据传输,后台服务等功能。</p>
</blockquote>
<h2 id="activity">Activity</h2>
<p>Activity是安卓应用中的活动界面,可以把它理解为Web中的一个窗口,通过这个窗口,我们可以展示不同的组件,从而形成能和用户交互的界面。</p>
<p>其生命周期如下:</p>
<p><img src="https://wanls4583.github.io/images/posts/移动端/activity-life.webp" alt="" /></p>
<p>首次执行app,将会依次执行onCreate、onStart、onResum,用户点击返回键退出程序时,将会依次执行onPause、onStop、onDestroy,当点击home键回到桌面时将会依次触犯onPause、onStop,如果Activity没有销毁,再次回到应用程序时将依次执行onRestart、onStart、onResum。</p>
<h2 id="service">Service</h2>
<p>Service主要用来运行后台任务。</p>
<p>其生命周期如下:</p>
<p><img src="https://wanls4583.github.io/images/posts/移动端/service-life.jpg" alt="" /></p>
<ul>
<li>一个service服务只有一个实例,服务启动后,应用程序需要绑定服务才可以访问。</li>
<li>即使Activity销毁后,服务依然可以运行,只有将应用程序所占的内存除后,或者显示调用stopService函数才能停止服务。</li>
<li>如果Activity有绑定服务,如果其销毁时没有接触绑定,将会报错。</li>
<li>对于已经被绑定的服务,执行stopService并不能触发onDestroy,这时,再次执行unbindService将会依次执行onUnbind、onDestory。</li>
</ul>
<h2 id="broadcastreciever">BroadCastReciever</h2>
<p>BroadCastReciever是广播接受者组件,可以接收本应用,或其他应用,又或者系统发出的广播消息。</p>
<p>广播接受者可以静态注册,也可以动态注册。对于静态注册的广播接受者,Android8.0以上不支持指定action过滤。Android8.0以后版本,官方不推荐使用静态注册,统一使用动态注册更加灵活。</p>
<p>对于静态注册的广播接受者,可以通过setComponent指定接受者来发送广播(Android8.0以上不支持指定action)。</p>
<h2 id="contentprovider">ContentProvider</h2>
<p>ContentProvider的作用是为不同的应用之间数据共享,提供统一的接口。</p>
<p>我们知道安卓系统中应用内部的数据是对外隔离的,要想让其它应用能使用自己的数据(例如通讯录)这个时候就用到了ContentProvider。</p>
<p>最简单的例子,手机里的联系人就是因为提供了ContentProvider接口,我们开发的应用程序才能访问到联系人信息。</p>
<h2 id="实例代码">实例代码</h2>
<p>MainActivity.java</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">com.example.myapplication</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.ComponentName</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.Context</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.Intent</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.IntentFilter</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.ServiceConnection</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.os.Bundle</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">androidx.appcompat.app.AppCompatActivity</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.os.IBinder</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.view.View</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.widget.Button</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MainActivity</span> <span class="kd">extends</span> <span class="nc">AppCompatActivity</span> <span class="kd">implements</span> <span class="nc">ServiceConnection</span><span class="o">,</span> <span class="nc">View</span><span class="o">.</span><span class="na">OnClickListener</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">Intent</span> <span class="n">serviceIntent</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">MyService</span><span class="o">.</span><span class="na">MyBinder</span> <span class="n">srvBinder</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">MyReceiver</span> <span class="n">myBc</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">MyReceiver</span><span class="o">();</span>
<span class="kd">private</span> <span class="kt">boolean</span> <span class="n">hasRegister</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onCreate</span><span class="o">(</span><span class="nc">Bundle</span> <span class="n">savedInstanceState</span><span class="o">)</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onCreate</span><span class="o">(</span><span class="n">savedInstanceState</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"acitvity onCreate"</span><span class="o">);</span>
<span class="n">setContentView</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">layout</span><span class="o">.</span><span class="na">activity_main</span><span class="o">);</span>
<span class="n">serviceIntent</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Intent</span><span class="o">(</span><span class="k">this</span><span class="o">,</span><span class="nc">MyService</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">startAtyBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">startAty1Btn</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">startSrvBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">startSrvBtn</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">stopSrvBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">stopSrvBtn</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">bindSrvBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">bindSrvBtn</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">unbindSrvBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">unbindSrvBtn</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">getCountBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">getCountBtn</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">sendBroadCastBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">sendBroadCastBtn</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">regRecieverBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">regRecieverBtn</span><span class="o">);</span>
<span class="nc">Button</span> <span class="n">unregRecieverBtn</span> <span class="o">=</span> <span class="n">findViewById</span><span class="o">(</span><span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">unregRecieverBtn</span><span class="o">);</span>
<span class="n">startAtyBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="n">startSrvBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="n">stopSrvBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="n">bindSrvBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="n">unbindSrvBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="n">getCountBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="n">sendBroadCastBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="n">regRecieverBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="n">unregRecieverBtn</span><span class="o">.</span><span class="na">setOnClickListener</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onStart</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onStart</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"acitvity onStart"</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onRestart</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onRestart</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"acitvity onRestart"</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onPause</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onPause</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"acitvity onPause"</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onStop</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onStop</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"acitvity onStop"</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onResume</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onResume</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"acitvity onResume"</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onDestroy</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onDestroy</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"acitvity onDestroy"</span><span class="o">);</span>
<span class="k">if</span><span class="o">(</span><span class="n">srvBinder</span><span class="o">!=</span><span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="n">unbindService</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="o">}</span>
<span class="k">if</span><span class="o">(</span><span class="n">hasRegister</span><span class="o">)</span> <span class="o">{</span>
<span class="n">unregisterReceiver</span><span class="o">(</span><span class="n">myBc</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onServiceConnected</span><span class="o">(</span><span class="nc">ComponentName</span> <span class="n">componentName</span><span class="o">,</span> <span class="nc">IBinder</span> <span class="n">iBinder</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"onServiceConnected"</span><span class="o">);</span>
<span class="n">srvBinder</span> <span class="o">=</span> <span class="o">(</span><span class="nc">MyService</span><span class="o">.</span><span class="na">MyBinder</span><span class="o">)</span> <span class="n">iBinder</span><span class="o">;</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onServiceDisconnected</span><span class="o">(</span><span class="nc">ComponentName</span> <span class="n">componentName</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"onServiceDisconnected"</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onClick</span><span class="o">(</span><span class="nc">View</span> <span class="n">view</span><span class="o">)</span> <span class="o">{</span>
<span class="k">switch</span> <span class="o">(</span><span class="n">view</span><span class="o">.</span><span class="na">getId</span><span class="o">())</span> <span class="o">{</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">startAty1Btn</span><span class="o">:</span>
<span class="nc">Intent</span> <span class="n">i</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Intent</span><span class="o">(</span><span class="nc">MainActivity</span><span class="o">.</span><span class="na">this</span><span class="o">,</span> <span class="nc">Activity1</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="n">i</span><span class="o">.</span><span class="na">putExtra</span><span class="o">(</span><span class="s">"txtName"</span><span class="o">,</span><span class="s">"this char is from main_aty"</span><span class="o">);</span>
<span class="n">startActivity</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">startSrvBtn</span><span class="o">:</span>
<span class="n">startService</span><span class="o">(</span><span class="n">serviceIntent</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">stopSrvBtn</span><span class="o">:</span>
<span class="n">stopService</span><span class="o">(</span><span class="n">serviceIntent</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">bindSrvBtn</span><span class="o">:</span>
<span class="n">bindService</span><span class="o">(</span><span class="n">serviceIntent</span><span class="o">,</span><span class="k">this</span><span class="o">,</span> <span class="nc">Context</span><span class="o">.</span><span class="na">BIND_AUTO_CREATE</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">unbindSrvBtn</span><span class="o">:</span>
<span class="n">unbindService</span><span class="o">(</span><span class="k">this</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">getCountBtn</span><span class="o">:</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">srvBinder</span><span class="o">.</span><span class="na">getCurrentCount</span><span class="o">());</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">sendBroadCastBtn</span><span class="o">:</span>
<span class="c1">//静态注册的广播接收器中指定的action其在android8.0以上无效</span>
<span class="c1">//Intent tmp = new Intent("com.example.myapplication.intent.action.TestAction");</span>
<span class="c1">//Intent tmp = new Intent(MainActivity.this,MyReceiver.class);</span>
<span class="nc">Intent</span> <span class="n">tmp</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Intent</span><span class="o">();</span>
<span class="c1">//用来发生给静态注册的广播接收者,这种方式也可以发送个其他应用的静态广播接收者</span>
<span class="n">tmp</span><span class="o">.</span><span class="na">setComponent</span><span class="o">(</span><span class="k">new</span> <span class="nc">ComponentName</span><span class="o">(</span><span class="s">"com.example.myapplication"</span><span class="o">,</span><span class="s">"com.example.myapplication.MyReceiver"</span><span class="o">));</span>
<span class="n">tmp</span><span class="o">.</span><span class="na">putExtra</span><span class="o">(</span><span class="s">"txtName"</span><span class="o">,</span><span class="s">"received broadcast txt"</span><span class="o">);</span>
<span class="n">sendBroadcast</span><span class="o">(</span><span class="n">tmp</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">regRecieverBtn</span><span class="o">:</span>
<span class="n">registerReceiver</span><span class="o">(</span><span class="n">myBc</span><span class="o">,</span> <span class="k">new</span> <span class="nc">IntentFilter</span><span class="o">(</span><span class="s">"com.example.myapplication.intent.action.TestAction"</span><span class="o">));</span>
<span class="n">hasRegister</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"registerReceiver"</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="k">case</span> <span class="no">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">unregRecieverBtn</span><span class="o">:</span>
<span class="n">unregisterReceiver</span><span class="o">(</span><span class="n">myBc</span><span class="o">);</span>
<span class="n">hasRegister</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"unregisterReceiver"</span><span class="o">);</span>
<span class="k">break</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>MyService.java</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">com.example.myapplication</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.app.Service</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.Intent</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.os.Binder</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.os.IBinder</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Timer</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.TimerTask</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyService</span> <span class="kd">extends</span> <span class="nc">Service</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">Integer</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">Timer</span> <span class="n">timer</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">TimerTask</span> <span class="n">task</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">MyService</span><span class="o">()</span> <span class="o">{</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onCreate</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onCreate</span><span class="o">();</span>
<span class="n">startTimer</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"service onCreate"</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onDestroy</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">super</span><span class="o">.</span><span class="na">onDestroy</span><span class="o">();</span>
<span class="n">stopTimer</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"service onDestroy"</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="nc">IBinder</span> <span class="nf">onBind</span><span class="o">(</span><span class="nc">Intent</span> <span class="n">intent</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// TODO: Return the communication channel to the service.</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"service onBind"</span><span class="o">);</span>
<span class="k">return</span> <span class="k">new</span> <span class="nf">MyBinder</span><span class="o">();</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">onUnbind</span><span class="o">(</span><span class="nc">Intent</span> <span class="n">intent</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"service onUnbind"</span><span class="o">);</span>
<span class="k">return</span> <span class="kd">super</span><span class="o">.</span><span class="na">onUnbind</span><span class="o">(</span><span class="n">intent</span><span class="o">);</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyBinder</span> <span class="kd">extends</span> <span class="nc">Binder</span> <span class="o">{</span>
<span class="kd">public</span> <span class="nc">Integer</span> <span class="nf">getCurrentCount</span><span class="o">(){</span>
<span class="k">return</span> <span class="nc">MyService</span><span class="o">.</span><span class="na">this</span><span class="o">.</span><span class="na">count</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">startTimer</span><span class="o">(){</span>
<span class="k">if</span><span class="o">(</span><span class="n">timer</span> <span class="o">==</span> <span class="kc">null</span><span class="o">){</span>
<span class="n">timer</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Timer</span><span class="o">();</span>
<span class="n">task</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TimerTask</span><span class="o">()</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span>
<span class="n">count</span><span class="o">++;</span>
<span class="o">}</span>
<span class="o">};</span>
<span class="n">timer</span><span class="o">.</span><span class="na">schedule</span><span class="o">(</span><span class="n">task</span><span class="o">,</span><span class="mi">1000</span><span class="o">,</span><span class="mi">1000</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">stopTimer</span><span class="o">()</span> <span class="o">{</span>
<span class="k">if</span><span class="o">(</span><span class="n">timer</span><span class="o">!=</span><span class="kc">null</span><span class="o">)</span> <span class="o">{</span>
<span class="n">timer</span><span class="o">.</span><span class="na">cancel</span><span class="o">();</span>
<span class="n">task</span><span class="o">.</span><span class="na">cancel</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>MyReceiver.java</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">com.example.myapplication</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.BroadcastReceiver</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.Context</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">android.content.Intent</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">MyReceiver</span> <span class="kd">extends</span> <span class="nc">BroadcastReceiver</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onReceive</span><span class="o">(</span><span class="nc">Context</span> <span class="n">context</span><span class="o">,</span> <span class="nc">Intent</span> <span class="n">intent</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// TODO: This method is called when the BroadcastReceiver is receiving</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"onReceive:"</span><span class="o">+</span><span class="n">intent</span><span class="o">.</span><span class="na">getStringExtra</span><span class="o">(</span><span class="s">"txtName"</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/移动端/安卓四大组件/MyApplication">完整代码</a></p>
C-LODOP打印控件使用心得
2019-08-03T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/08/03/C-LODOP打印控件使用心得
<h2 id="c-lodop">C-LODOP</h2>
<blockquote>
<p>Lodop 是专业WEB控件,用它既可裁剪输出页面内容,又可用程序代码直接实现复杂打印。控件功能强大,却简单易用,所有调用如同 JavaScript 扩展语句。</p>
</blockquote>
<p>简单使用:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">pageBreakJs</span> <span class="o">=</span> <span class="dl">'</span><span class="s1"><script src="/js/page_break/v1.0/index.js"></script></span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">strStyleCSS</span> <span class="o">+=</span> <span class="dl">'</span><span class="s1"><style>.test{background-color:red}</style></span><span class="dl">'</span><span class="p">;</span>
<span class="nx">strStyleCSS</span> <span class="o">+=</span> <span class="dl">'</span><span class="s1"><link href="test.css" rel="stylesheet"></span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">LODOP</span> <span class="o">=</span> <span class="nx">getLodop</span><span class="p">();</span>
<span class="nx">LODOP</span><span class="p">.</span><span class="nx">PRINT_INIT</span><span class="p">(</span><span class="dl">''</span><span class="p">);</span>
<span class="nx">LODOP</span><span class="p">.</span><span class="nx">ADD_PRINT_HTM</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="dl">"</span><span class="s2">100%</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">100%</span><span class="dl">"</span><span class="p">,</span> <span class="dl">'</span><span class="s1"><!DOCTYPE html><head></span><span class="dl">'</span> <span class="o">+</span> <span class="nx">strStyleCSS</span> <span class="o">+</span> <span class="dl">"</span><span class="s2"></head><body style='background-color: #ffffff;overflow:hidden;'></span><span class="dl">"</span> <span class="o">+</span> <span class="nx">printHTML</span> <span class="o">+</span> <span class="nx">pageBreakJs</span> <span class="o">+</span> <span class="dl">"</span><span class="s2"></body></html></span><span class="dl">"</span><span class="p">);</span>
<span class="nx">LODOP</span><span class="p">.</span><span class="nx">PREVIEW</span><span class="p">(</span><span class="dl">''</span><span class="p">);</span>
</code></pre></div></div>
<p>通过使用 <strong>ADD_PRINT_HTM</strong> 方法,可以传入 HTML 内容 、 CSS 、 JS,CLODOP 插件内部会调用本机默认 ie 内核进行渲染,其渲染的结果将作为最终输出,其本质和浏览器一样,所以也可以运行 javascript 脚本。为了应对不同客户端电脑不同 ie 版本,需要对低版本 ie 内核进行兼容。</p>
<p>注意事项:</p>
<ul>
<li>如果需要在 ADD_PRINT_HTM 种执行脚本或者使用自定义样式,最好使用内联脚本和内联样式,在 win7 或者 xp 系统中,加载外部文件会消耗大量CPU资源,可能会造成预览框弹不出(不知道是电脑配置问题还是插件的bug)。</li>
<li>使用 ADD_PRINT_HTM 打印 HTML 内容不能进行很好的自动分页,在页面底部如果刚好有文字,文字可能被截掉一半,解决这种问题,目前只能手动进行强制换行,或者加入脚本动态计算,如下:
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//css:.break_page{page-break-after:always}</span>
<span class="c1">//以下代码需要添加到 ADD_PRINT_HTM 的内容中</span>
<span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">doms</span> <span class="o">=</span> <span class="nx">_getByClass</span><span class="p">(</span><span class="dl">'</span><span class="s1">count_height</span><span class="dl">'</span><span class="p">);</span> <span class="c1">//需要事先给不能分页的元素添加'count_height'类</span>
<span class="c1">//获取打印机纸张高度</span>
<span class="kd">var</span> <span class="nx">windowHeight</span> <span class="o">=</span> <span class="nb">window</span><span class="p">.</span><span class="nx">innerHeight</span> <span class="o">||</span> <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">.</span><span class="nx">clientHeight</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">countHeight</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">doms</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//计算元素所占的高度</span>
<span class="kd">var</span> <span class="nx">height</span> <span class="o">=</span> <span class="nx">doms</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">scrollHeight</span> <span class="o">+</span> <span class="nx">_getMargin</span><span class="p">(</span><span class="nx">doms</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="dl">'</span><span class="s1">marginTop</span><span class="dl">'</span><span class="p">)</span> <span class="o">+</span> <span class="nx">_getMargin</span><span class="p">(</span><span class="nx">doms</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span> <span class="dl">'</span><span class="s1">marginBottom</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">countHeight</span> <span class="o">+=</span> <span class="nx">height</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">countHeight</span> <span class="o">+</span> <span class="mi">50</span> <span class="o">></span> <span class="nx">windowHeight</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//该元素正好在分页部位,则强制到下一页显示</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">i</span> <span class="o">></span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">doms</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="nx">className</span> <span class="o">=</span> <span class="nx">doms</span><span class="p">[</span><span class="nx">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">].</span><span class="nx">className</span> <span class="o">+</span> <span class="dl">'</span><span class="s1"> break_page</span><span class="dl">'</span>
<span class="p">}</span>
<span class="nx">countHeight</span> <span class="o">=</span> <span class="nx">height</span> <span class="o">%</span> <span class="nx">windowHeight</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//获取边距</span>
<span class="kd">function</span> <span class="nx">_getMargin</span><span class="p">(</span><span class="nx">dom</span><span class="p">,</span> <span class="nx">prop</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">getComputedStyle</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">_pxToNum</span><span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">getComputedStyle</span><span class="p">(</span><span class="nx">dom</span><span class="p">,</span> <span class="kc">null</span><span class="p">)[</span><span class="nx">prop</span><span class="p">]);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">_pxToNum</span><span class="p">(</span><span class="nx">dom</span><span class="p">.</span><span class="nx">currentStyle</span><span class="p">[</span><span class="nx">prop</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//去掉px单位</span>
<span class="kd">function</span> <span class="nx">_pxToNum</span><span class="p">(</span><span class="nx">px</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">px</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="nx">px</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">2</span><span class="p">))</span> <span class="o">||</span> <span class="mi">0</span>
<span class="p">}</span>
<span class="c1">//兼容ie6</span>
<span class="kd">function</span> <span class="nx">_getByClass</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//如果浏览器支持 会得到一个函数体</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByClassName</span><span class="p">(</span><span class="nx">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//把所有的元素获取到</span>
<span class="kd">var</span> <span class="nx">allItems</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="dl">"</span><span class="s2">div</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">newArr</span> <span class="o">=</span> <span class="p">[];</span>
<span class="c1">//查找每一个元素的className 看其中含不含name</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">allItems</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">classNames</span> <span class="o">=</span> <span class="nx">allItems</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">className</span><span class="p">;</span> <span class="c1">//"test test11"</span>
<span class="kd">var</span> <span class="nx">arrClass</span> <span class="o">=</span> <span class="nx">classNames</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2"> </span><span class="dl">"</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o"><</span> <span class="nx">arrClass</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">arrClass</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o">==</span> <span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">newArr</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">allItems</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">newArr</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">})();</span>
</code></pre></div> </div>
</li>
</ul>
post跨域请求
2019-07-05T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/07/05/post跨域请求
<blockquote>
<p>通常情况下,如果服务器不设置跨域头,页面是获取不到非同域下的post请求数据。利用form+iframe,通过父子页面的数据传递可以实现post跨越请求。</p>
</blockquote>
<p>有两种方式可以实现父子页面的数据传递。针对支持HTML5的浏览器可以使用postMessage来实现,这种方式支持不同主域页面之间的数据传递。而另外一种是使用回调函数来实现,这种方式只支持同主域(子域名可能不同)页面之间的数据传递。</p>
<h2 id="回调函数方式">回调函数方式</h2>
<p>示例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>post跨越请求<span class="nt"></title></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"doPost('testFn');"</span><span class="nt">></span>发送请求<span class="nt"></button></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nb">document</span><span class="p">.</span><span class="nx">domain</span><span class="o">=</span><span class="dl">"</span><span class="s2">test.com</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">doPost</span><span class="p">(</span><span class="nx">callbackName</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">callbackName</span><span class="p">:</span> <span class="nx">callbackName</span>
<span class="p">}</span>
<span class="c1">//解决ie7以下设置name无效的bug</span>
<span class="kd">var</span> <span class="nx">iframe</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">all</span> <span class="p">?</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1"><iframe name="myFrame"></iframe></span><span class="dl">'</span><span class="p">)</span> <span class="p">:</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">iframe</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">iframe</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">iframe</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">iframe</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">myFrame</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">form</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">form</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">iframe</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">target</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">myFrame</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">action</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">http://a.test.com:8080/api/1</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">method</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">post</span><span class="dl">'</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">key</span> <span class="k">in</span> <span class="nx">obj</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">input</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">input</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">input</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">key</span><span class="p">;</span>
<span class="nx">input</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">input</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">iframe</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">form</span><span class="p">);</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">submit</span><span class="p">();</span>
<span class="nb">window</span><span class="p">[</span><span class="nx">callbackName</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="nx">iframe</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">iframe</span><span class="p">);</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">form</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>server.js</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">express</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">fs</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">mime</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">mime</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">bodyParser</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">body-parser</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">bodyParser</span><span class="p">.</span><span class="nx">json</span><span class="p">());</span><span class="c1">//数据JSON类型</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">bodyParser</span><span class="p">.</span><span class="nx">urlencoded</span><span class="p">({</span> <span class="na">extended</span><span class="p">:</span> <span class="kc">false</span> <span class="p">}));</span><span class="c1">//解析post请求数据</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/api/1</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">`<script>document.domain="test.com";window.parent.</span><span class="p">${</span><span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">callbackName</span><span class="p">}</span><span class="s2">('服务器数据')</script>`</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/api/2</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">`<script>window.parent.postMessage('服务器数据','*')</script>`</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/*</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="nx">sendFile</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">listen 8080</span><span class="dl">'</span><span class="p">)</span>
<span class="kd">function</span> <span class="nx">sendFile</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">realPath</span> <span class="o">=</span> <span class="nx">__dirname</span><span class="o">+</span><span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">exist</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">existsSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">exist</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">file</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="nx">mime</span><span class="p">.</span><span class="nx">getType</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">realPath</span><span class="p">)),</span>
<span class="p">});</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="nx">file</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">send static file:</span><span class="dl">'</span><span class="o">+</span><span class="nx">realPath</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">404</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/其他/cross-post">示例代码</a></p>
<p>注意:</p>
<ul>
<li>服务器X-Frame-Options不能设置成DENY</li>
<li>父页面和子页面的主域必须相同(上面父子页面的主域为<code class="language-plaintext highlighter-rouge">test.com</code>),<strong>并且父子页面都必须显示的设置domain为主域,即使父页面本身就是主域名</strong>。</li>
</ul>
<h2 id="postmessage方式">postMessage方式</h2>
<p>实例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>post跨越请求<span class="nt"></title></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"doPost();"</span><span class="nt">></span>发送请求<span class="nt"></button></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">doPost</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">iframe</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">iframe</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">form</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">form</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">iframe</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">myFrame</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">iframe</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">display</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">none</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">target</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">myFrame</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">action</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">http://a.test.com:8080/api/2</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">method</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">post</span><span class="dl">'</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">iframe</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">form</span><span class="p">);</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">submit</span><span class="p">();</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onmessage</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">data</span><span class="p">);</span>
<span class="nx">iframe</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">iframe</span><span class="p">);</span>
<span class="nx">form</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">form</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
jsonp实现原理
2019-07-05T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/07/05/jsonp实现原理
<blockquote>
<p>jsonp通过动态请求脚本文件,可以非常方便的实现不同域名下的数据请求,不过该方法只能发送get请求。</p>
</blockquote>
<p>示例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>jsonp<span class="nt"></title></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"doJsonp('testFn');"</span><span class="nt">></span>发送JSONP请求<span class="nt"></button></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">doJsonp</span><span class="p">(</span><span class="nx">callbackName</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">script</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">script</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">script</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">/api?callbackName=</span><span class="dl">'</span><span class="o">+</span><span class="nx">callbackName</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="dl">'</span><span class="s1">head</span><span class="dl">'</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">script</span><span class="p">);</span>
<span class="nb">window</span><span class="p">[</span><span class="nx">callbackName</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="nx">script</span><span class="p">.</span><span class="nx">parentNode</span><span class="p">.</span><span class="nx">removeChild</span><span class="p">(</span><span class="nx">script</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>server.js</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">express</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">fs</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">mime</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">mime</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">bodyParser</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">body-parser</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">bodyParser</span><span class="p">.</span><span class="nx">json</span><span class="p">());</span><span class="c1">//数据JSON类型</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">use</span><span class="p">(</span><span class="nx">bodyParser</span><span class="p">.</span><span class="nx">urlencoded</span><span class="p">({</span> <span class="na">extended</span><span class="p">:</span> <span class="kc">false</span> <span class="p">}));</span><span class="c1">//解析post请求数据</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/api</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">req</span><span class="p">.</span><span class="nx">query</span><span class="p">.</span><span class="nx">callbackName</span><span class="p">}</span><span class="s2">('服务器数据')`</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/*</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="nx">sendFile</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">listen 8080</span><span class="dl">'</span><span class="p">)</span>
<span class="kd">function</span> <span class="nx">sendFile</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">realPath</span> <span class="o">=</span> <span class="nx">__dirname</span><span class="o">+</span><span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">exist</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">existsSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">exist</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">file</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="nx">mime</span><span class="p">.</span><span class="nx">getType</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">realPath</span><span class="p">)),</span>
<span class="p">});</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="nx">file</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">send static file:</span><span class="dl">'</span><span class="o">+</span><span class="nx">realPath</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">404</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/其他/jsonp">示例代码</a></p>
ie8-无刷新上传
2019-07-05T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/07/05/ie8-无刷新上传
<blockquote>
<p>ie8及以下浏览器不支持ajax来上传文件,可通过iframe来实现无刷新上传,原理参考<a href="https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/07/05/post%E8%B7%A8%E8%B6%8A%E8%AF%B7%E6%B1%82/">post跨越请求</a></p>
</blockquote>
<p>示例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>ie8-无刷新上传<span class="nt"></title></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">suc</span><span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">myFrame</span><span class="p">.</span><span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">innerHTML</span><span class="p">);</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><form</span> <span class="na">action=</span><span class="s">"http://localhost:8080/api"</span> <span class="na">target=</span><span class="s">"myFrame"</span> <span class="na">method=</span><span class="s">"post"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"file"</span> <span class="na">name=</span><span class="s">"test"</span><span class="nt">></span>
<span class="nt"><input</span> <span class="na">type=</span><span class="s">"submit"</span> <span class="na">value=</span><span class="s">"提交"</span> <span class="na">onclick=</span><span class="s">"submit()"</span><span class="nt">></span>
<span class="nt"></form></span>
<span class="nt"><iframe</span> <span class="na">name=</span><span class="s">"myFrame"</span> <span class="na">onload=</span><span class="s">"suc()"</span> <span class="na">style=</span><span class="s">"display: none;"</span><span class="nt">></iframe></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>server.js</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">express</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">fs</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">mime</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">mime</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">app</span> <span class="o">=</span> <span class="nx">express</span><span class="p">();</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/api</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">send</span><span class="p">(</span><span class="s2">`服务器数据`</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">app</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/*</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="nx">sendFile</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">app</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">8080</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">listen 8080</span><span class="dl">'</span><span class="p">)</span>
<span class="kd">function</span> <span class="nx">sendFile</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">realPath</span> <span class="o">=</span> <span class="nx">__dirname</span><span class="o">+</span><span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">exist</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">existsSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">exist</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">file</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="nx">mime</span><span class="p">.</span><span class="nx">getType</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">realPath</span><span class="p">)),</span>
<span class="p">});</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="nx">file</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">send static file:</span><span class="dl">'</span><span class="o">+</span><span class="nx">realPath</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">404</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/其他/ie8-upload">示例代码</a></p>
<p>注意:</p>
<ul>
<li>服务器X-Frame-Options不能设置成DENY</li>
<li>使用该方式获取子页面数据,父子页面需要在同域下</li>
</ul>
前端性能优化之-PWA(vue中接入pwa实践)
2019-02-27T16:19:00+00:00
https://blog.lisong.hn.cn/2019/02/27/前端性能优化之-PWA(vue中接入pwa实践)
<blockquote>
<p>目前的应用中,pwa主要用来实现离线存储静态文件(当然还有推送功能,目前看来比较鸡肋),使其在断网的情况下依然可以被浏览器加载。</p>
</blockquote>
<h2 id="在vue中使用pwa">在vue中使用pwa</h2>
<p>1.manifest.json:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="dl">"</span><span class="s2">scope</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">音盟发布后台</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">short_name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">音盟发布后台</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">start_url</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">/</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">display</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">standalone</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">description</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">音盟发布后台</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">orientation</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">portrait</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">theme_color</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">#f9d67e</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">background_color</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">#fff</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">icons</span><span class="dl">"</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="dl">"</span><span class="s2">src</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">./img/logo.png</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">sizes</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">48x48</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">image/png</span><span class="dl">"</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="dl">"</span><span class="s2">src</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">./img/logo.png</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">sizes</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">144x144</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">type</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">image/png</span><span class="dl">"</span>
<span class="p">}]</span>
<span class="p">}</span>
</code></pre></div></div>
<p>2.index.html:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"manifest"</span> <span class="na">href=</span><span class="s">"/static/manifest.json"</span><span class="nt">></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="dl">'</span><span class="s1">serviceWorker</span><span class="dl">'</span> <span class="k">in</span> <span class="nb">navigator</span> <span class="o">&&</span> <span class="nx">location</span><span class="p">.</span><span class="nx">protocol</span><span class="o">==</span><span class="dl">'</span><span class="s1">https:</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//注册service-worker,必须是https(localhost除外)</span>
<span class="nb">navigator</span><span class="p">.</span><span class="nx">serviceWorker</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="dl">'</span><span class="s1">/service-worker.js</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">})();</span>
<span class="nt"></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>3.使用<code class="language-plaintext highlighter-rouge">sw-precache-webpack-plugin</code>插件</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="kd">const</span> <span class="nx">SWPrecacheWebpackPlugin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">sw-precache-webpack-plugin</span><span class="dl">'</span><span class="p">)</span>
<span class="p">...</span>
<span class="k">new</span> <span class="nx">SWPrecacheWebpackPlugin</span><span class="p">({</span>
<span class="na">cacheId</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ym-app</span><span class="dl">'</span><span class="p">,</span>
<span class="na">staticFileGlobs</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">dist/**/*.{js,html,css}</span><span class="dl">'</span><span class="p">],</span>
<span class="na">minify</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">stripPrefix</span><span class="p">:</span> <span class="dl">'</span><span class="s1">dist/</span><span class="dl">'</span>
<span class="p">})</span>
<span class="p">...</span>
</code></pre></div></div>
<p>build之后其会在dist目录下生成一个<code class="language-plaintext highlighter-rouge">service-worker.js</code>文件。其代码住流程如下:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">...</span>
<span class="c1">//每个需要存储的文件对应一个hash,文件变化时,service-worker.js 中的对应的hash也会变化</span>
<span class="kd">var</span> <span class="nx">precacheConfig</span> <span class="o">=</span> <span class="p">[[</span><span class="dl">"</span><span class="s2">index.html</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">d38edf8db59e7dd91ccb877ef163d31b</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">service-worker.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">5c0c0cbecb8544bfcc687c909fd49cdc</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/css/app.fef1abee3f12f21e218ddec1d58b6fc6.css</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">2a77574058b3438fb5f7cce4513a8bb4</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/html/wxLogin.html</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">e0ed73f05b7922414e1005dc41ca28c1</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/0.3f2be2a020b3a94ac1ea.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">41e7823410b3b65e738d382cfe21cc62</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/1.5143706b17b1bc69d45d.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">47366bb0197080021e0c7fd46f7d5c9f</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/12.934297257cdd3d0c2260.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">6ff8adb94666b3b8594dad94c81876df</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/13.121bcdf047b663540110.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">52581bea367c2d6d17fb88450a0fd2cf</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/14.2b6c69e731f113365755.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">7911ad600864deefc0e8e8caf670faaa</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/2.5a19dea541f93af2e6b4.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">542c99e30546905ca44d03787424a9c5</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/3.12f6287ab8242457ef6a.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">efc489a57473fe2934f4fd5728e89f6e</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/4.a220248c2802112f4cef.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">2f4da6289567ba71a3d6476f29ef77ec</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/5.3d3259fc69baa8ef3ca5.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">3442a26bd866862c6cc7973954023531</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/6.e8f023f6bc3b547719ac.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">4de3cf7108a0333fe14f56d469dd33c3</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/7.15fe9ce8ca404aebf40b.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">89f3c3591836ff7c0531cc68a39244f0</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/8.0606f59eefd3b8235495.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">6043047d95c69b50db6bfb6404aeed86</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/9.2147611e55ffe0ebb062.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">25e5bac14378c1f860411e47f21631b4</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/app.735923e393b696a5cddd.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">004363266ab53430477e47020161d552</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/manifest.0244e595627d2cf52aaa.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">96756f50ccc73262740afff811cb7051</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/vendor.433132e77c4d31c0d66f.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">9336d0a614cfc7adc3af0858e58e1cc6</span><span class="dl">"</span><span class="p">],</span> <span class="p">[</span><span class="dl">"</span><span class="s2">static/js/wxLogin.js</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">5a676b71d687d7c323df7e7980eecd55</span><span class="dl">"</span><span class="p">]],</span>
<span class="p">...</span>
<span class="c1">//注册事件(每次 service-workder.js 文件有改变时都会重新注册)</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">install</span><span class="dl">"</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="c1">//预加载 precacheConfig 中的文件(链接后面会加上hash参数),将其存储到cache</span>
<span class="p">});</span>
<span class="c1">//激活事件(触发install后,会接着触发该事件)</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">install</span><span class="dl">"</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="c1">//检查所有可用的存储条目,根据hash值判断是否有效,无效则将其cache中删除出</span>
<span class="p">});</span>
<span class="c1">//拦截请求</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">fetch</span><span class="dl">"</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="c1">//如果cache中存在该文件,则直接返回,否则从服务器拉取最新的文件</span>
<span class="p">});</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">sw-precache-webpack-plugin</code>插件的主要作用为生成一个<code class="language-plaintext highlighter-rouge">service-workder.js</code>文件,每次当相应的文件有改变时,其内容也会更改,这样浏览器又会重新注册service-worker。</p>
<p><strong>注意:正式环境必须是https协议</strong></p>
jenkins参数化构建
2019-02-15T17:27:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/02/15/jenkins参数化构建
<p>以下配置用来实现服务器的web相关文件的恢复:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins参数化构建-1.png" alt="" /></p>
<p><strong>以上配置的 project 是选项参数,一行代表一个参数</strong></p>
<p>构建时就可以选择参数了</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins参数化构建-2.png" alt="" /></p>
js模拟实现call,apply,bind
2019-02-15T12:02:00+00:00
https://blog.lisong.hn.cn/javascript/2019/02/15/js模拟实现call,apply,bind
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">myCall</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">context</span> <span class="o">!=</span> <span class="dl">'</span><span class="s1">object</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">fn</span> <span class="o">=</span> <span class="nb">Symbol</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="nx">i</span><span class="o"><</span><span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">args</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">arguments</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="nx">context</span><span class="p">[</span><span class="nx">fn</span><span class="p">]</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="nx">context</span><span class="p">[</span><span class="nx">fn</span><span class="p">](...</span><span class="nx">args</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">myApply</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">context</span> <span class="o">!=</span> <span class="dl">'</span><span class="s1">object</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">fn</span> <span class="o">=</span> <span class="nb">Symbol</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">args</span> <span class="o">=</span> <span class="nx">arguments</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="p">?</span> <span class="nx">arguments</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="p">:</span> <span class="p">[];</span>
<span class="nx">context</span><span class="p">[</span><span class="nx">fn</span><span class="p">]</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="nx">context</span><span class="p">[</span><span class="nx">fn</span><span class="p">](...</span><span class="nx">args</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">myBind</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">context</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nb">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">context</span><span class="p">,</span><span class="nx">arguments</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">test</span><span class="p">(</span><span class="nx">arg</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">name</span><span class="p">,</span><span class="nx">arg</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">lisong</span><span class="dl">'</span>
<span class="p">};</span>
<span class="nx">test</span><span class="p">.</span><span class="nx">myCall</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span><span class="dl">'</span><span class="s1">testCall</span><span class="dl">'</span><span class="p">);</span> <span class="c1">//lisong testCall</span>
<span class="nx">test</span><span class="p">.</span><span class="nx">myApply</span><span class="p">(</span><span class="nx">obj</span><span class="p">,[</span><span class="dl">'</span><span class="s1">testApply</span><span class="dl">'</span><span class="p">]);</span> <span class="c1">//lisong testApply</span>
<span class="nx">test</span><span class="p">.</span><span class="nx">myBind</span><span class="p">(</span><span class="nx">obj</span><span class="p">)(</span><span class="dl">'</span><span class="s1">testBind</span><span class="dl">'</span><span class="p">);</span> <span class="c1">//lisong testBind</span>
</code></pre></div></div>
js函数柯里化
2019-02-14T19:20:00+00:00
https://blog.lisong.hn.cn/javascript/2019/02/14/js函数柯里化
<blockquote>
<p>柯里化的简单概念:只传递给函数一部分参数来调用它,让它返回一个函数去处理其他的参数。</p>
</blockquote>
<h2 id="参数个数确定的函数的柯里化">参数个数确定的函数的柯里化</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">add</span><span class="p">(</span><span class="nx">a</span><span class="p">){</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">b</span><span class="p">){</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">a</span><span class="o">+</span><span class="nx">b</span><span class="o">+</span><span class="nx">c</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">add</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="mi">2</span><span class="p">)(</span><span class="mi">3</span><span class="p">)</span> <span class="c1">//6</span>
</code></pre></div></div>
<h2 id="参数个数不确定的函数的柯里化">参数个数不确定的函数的柯里化</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">add</span><span class="p">(</span><span class="nx">a</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">_add</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="nx">a</span><span class="o">!=</span><span class="kc">undefined</span><span class="p">){</span> <span class="c1">//参数为空,证明处理完了</span>
<span class="nx">sum</span><span class="o">+=</span><span class="nx">a</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">_add</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nx">sum</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">_add</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">add</span><span class="p">(</span><span class="mi">1</span><span class="p">)(</span><span class="mi">2</span><span class="p">)(</span><span class="mi">3</span><span class="p">)(</span><span class="mi">4</span><span class="p">)()</span> <span class="c1">//10</span>
</code></pre></div></div>
js作用域
2019-02-14T18:24:00+00:00
https://blog.lisong.hn.cn/javascript/2019/02/14/js作用域
<p>对于编程语言来说,存在着两种类型的作用域,分别为静态作用域和动态作用域。作用域类别影响变量的绑定方式。</p>
<p>静态作用域又叫词法作用域。在词法作用域里,取变量的值时,会检查函数定义时的文本环境,捕捉函数定义时对该变量的绑定。大多数现在程序设计语言都是采用静态作用域规则,如C/C++、C#、Python、Java、JavaScript……</p>
<p>采用动态作用域的变量叫做动态变量。只要程序正在执行定义了动态变量的代码段,那么在这段时间内,该变量一直存在;代码段执行结束,该变量便消失。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">b</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">Test</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">a</span><span class="dl">'</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">getA</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">a</span><span class="p">;</span> <span class="c1">//对于静态作用域来说,词法解析时已经确定了</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">getB</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">b</span><span class="p">;</span> <span class="c1">//局部作用域没有,会继续向上级作用域查找</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Test</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">getA</span><span class="p">()(),</span><span class="nx">obj</span><span class="p">.</span><span class="nx">getB</span><span class="p">()());</span> <span class="c1">//a b</span>
</code></pre></div></div>
js防抖与节流
2019-02-14T15:50:00+00:00
https://blog.lisong.hn.cn/javascript/2019/02/14/js防抖与节流
<h2 id="防抖函数">防抖函数</h2>
<p>主要要来防止频繁调用某一事件的回调,其规定在某一延迟内,如果继续有事件触发,则计时器重新开始计时</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">debounce</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">cb</span><span class="p">,</span><span class="nx">delay</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">timer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">clearTimeout</span><span class="p">(</span><span class="nx">timer</span><span class="p">);</span>
<span class="nx">timer</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">cb</span><span class="p">();</span>
<span class="p">},</span><span class="nx">delay</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">foo</span> <span class="o">=</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">scroll</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.wrap</span><span class="dl">'</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">scroll</span><span class="dl">'</span><span class="p">,</span> <span class="nx">debounce</span><span class="p">(</span><span class="nx">foo</span><span class="p">,</span> <span class="mi">2000</span><span class="p">));</span>
</code></pre></div></div>
<h2 id="节流函数">节流函数</h2>
<p>节流函数类似防抖函数,也是用来解决事件的频繁触发,不过其能保证在事件发生后,在规定延迟后至少会执行一次</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">throttle</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">cb</span><span class="p">,</span> <span class="nx">delay</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">timer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">timer</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">timer</span> <span class="o">=</span> <span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">cb</span><span class="p">();</span>
<span class="nx">timer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">},</span><span class="nx">delay</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.wrap</span><span class="dl">'</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">scroll</span><span class="dl">'</span><span class="p">,</span> <span class="nx">throttle</span><span class="p">(</span><span class="nx">foo</span><span class="p">,</span> <span class="mi">2000</span><span class="p">));</span>
</code></pre></div></div>
webpack的动态引入与动态加载
2019-02-14T00:00:00+00:00
https://blog.lisong.hn.cn/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/2019/02/14/webpack的动态引入与动态加载
<h2 id="动态引入文件">动态引入文件</h2>
<p>有时我们想动态引入某个文件夹下的所有模块,文件名称事先是不知道的,这时可以使用 <code class="language-plaintext highlighter-rouge">require.context</code> 来实现该需求</p>
<p>mod/mod1.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="k">default</span> <span class="p">{</span>
<span class="na">name</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">mod1</span><span class="dl">'</span>
<span class="p">}</span>
</code></pre></div></div>
<p>mod/mod2.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">export</span> <span class="k">default</span> <span class="p">{</span>
<span class="na">name</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">mod2</span><span class="dl">'</span>
<span class="p">}</span>
</code></pre></div></div>
<p>index.js</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">files</span> <span class="o">=</span> <span class="nx">require</span><span class="p">.</span><span class="nx">context</span><span class="p">(</span><span class="dl">'</span><span class="s1">./mod</span><span class="dl">'</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">js$/</span><span class="p">)</span> <span class="c1">//第一个参数可以使用正则,第二个参数用来指定是否要递归子目录</span>
<span class="kd">const</span> <span class="nx">modules</span> <span class="o">=</span> <span class="p">{}</span>
<span class="nx">files</span><span class="p">.</span><span class="nx">keys</span><span class="p">().</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">key</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">key</span><span class="p">,</span><span class="nx">files</span><span class="p">(</span><span class="nx">key</span><span class="p">).</span><span class="k">default</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
<span class="nx">modules</span><span class="p">[</span><span class="nx">key</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">(\.\/</span><span class="sr">|</span><span class="se">\.</span><span class="sr">js</span><span class="se">)</span><span class="sr">/g</span><span class="p">,</span> <span class="dl">''</span><span class="p">)]</span> <span class="o">=</span> <span class="nx">files</span><span class="p">(</span><span class="nx">key</span><span class="p">).</span><span class="k">default</span><span class="p">;</span>
<span class="p">})</span>
<span class="k">export</span> <span class="k">default</span> <span class="nx">modules</span><span class="p">;</span>
</code></pre></div></div>
<p>运行结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/webpack的动态引入与动态加载-1.png" alt="" /></p>
<h2 id="动态加载模块">动态加载模块</h2>
<p>(一)vue路由的的动态加载:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="p">{</span>
<span class="nl">path</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span>
<span class="nx">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Content</span><span class="dl">'</span><span class="p">,</span>
<span class="nx">component</span><span class="p">:</span> <span class="nx">resolve</span> <span class="o">=></span> <span class="nx">require</span><span class="p">([</span><span class="dl">'</span><span class="s1">@/pages/Content</span><span class="dl">'</span><span class="p">],</span> <span class="nx">resolve</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>
<p>或者使用 es6 的方式</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="p">{</span>
<span class="nl">path</span><span class="p">:</span> <span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span>
<span class="nx">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">Content</span><span class="dl">'</span><span class="p">,</span>
<span class="nx">component</span><span class="p">:</span> <span class="p">()</span> <span class="o">=></span> <span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">@/pages/Content</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>
<p>(二)模块的动态加载</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nx">require</span><span class="p">.</span><span class="nx">ensure</span><span class="p">([],</span> <span class="p">(</span><span class="nx">require</span><span class="p">)</span><span class="o">=></span><span class="p">{</span> <span class="c1">//懒加载阿里云sdk</span>
<span class="kd">var</span> <span class="nx">OSS</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">ali-oss</span><span class="dl">'</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_initOSS</span><span class="p">(</span><span class="nx">OSS</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>或者使用 es6 的方式</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">import</span><span class="p">(</span><span class="dl">'</span><span class="s1">ali-oss</span><span class="dl">'</span><span class="p">).</span><span class="nx">then</span><span class="p">((</span><span class="nx">OSS</span><span class="p">)</span><span class="o">=></span><span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_initOSS</span><span class="p">(</span><span class="nx">OSS</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
使用jenkins构建vue项目与分布式部署
2019-02-13T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2019/02/13/使用jenkins构建vue项目与分布式部署
<h2 id="一分布式部署拓扑图">一、分布式部署拓扑图</h2>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/使用jenkins构建vue项目与分布式部署-1.png" alt="" /></p>
<h2 id="二配置远程服务器">二、配置远程服务器</h2>
<p>可以使用<code class="language-plaintext highlighter-rouge">Publish Over SSH</code>插件来实现linux服务器之间的免密码登录,其步骤如下:</p>
<ol>
<li>在 jenkins 服务器上安装<code class="language-plaintext highlighter-rouge">Publish Over SSH</code>插件</li>
<li>生成RSA秘钥对</li>
<li>将公钥配置到远程的三台机(10.32.0.223,10.33.0.11,10.167.0.246),将公钥添加到<code class="language-plaintext highlighter-rouge">/root/.ssh/authorized_keys</code>文件即可</li>
<li>将私钥添加到<code class="language-plaintext highlighter-rouge">Publish Over SSH</code>的配置中</li>
<li>在<code class="language-plaintext highlighter-rouge">Publish Over SSH</code>的配置中添加远程服务器</li>
</ol>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/使用jenkins构建vue项目与分布式部署-2.png" alt="" /></p>
<p>注意 <code class="language-plaintext highlighter-rouge">jenkins_publish_dir</code> 目录在远程服务器上的 root 账户下必须存在,通过SSH传输的文件默认会放在该目录下</p>
<h2 id="三配置触发器构建等操作">三、配置触发器、构建等操作</h2>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/使用jenkins构建vue项目与分布式部署-3.png" alt="" /></p>
<p>因为我们jenkins执行的操作涉及到 sudo,所以需要在jenkins服务器配置 jenkins 账号的免密权限</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/使用jenkins构建vue项目与分布式部署-4.png" alt="" /></p>
<p>经过上面的配置,只要git用户lisong有提交(提交的注释信息后面必须是-deploy),则jenkins会自动拉取代码并构建,最后分发到远程的三台机子</p>
webpack的几种引用方式
2018-12-22T00:00:00+00:00
https://blog.lisong.hn.cn/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/2018/12/22/webpack的几种引用方式
<p>a.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modA run</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">varA</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">modA</span><span class="dl">'</span><span class="p">;</span> <span class="c1">//模块内部的变量在其他模块是获取不到的,全局作用域的变量可以放在 window 下</span>
<span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">){</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">modA</span><span class="dl">'</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div></div>
<p>b.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./a</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modB run</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">modB</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p>c.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modC run</span><span class="dl">'</span><span class="p">);</span>
<span class="k">export</span> <span class="k">default</span> <span class="dl">'</span><span class="s1">modC</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p>d.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modD run</span><span class="dl">'</span><span class="p">);</span>
<span class="k">export</span> <span class="kd">var</span> <span class="nx">mod</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">modD</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./a</span><span class="dl">'</span><span class="p">);</span> <span class="c1">//等价于 import c from './c'; //webpack做了兼容处理</span>
<span class="k">import</span> <span class="nx">b</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./b</span><span class="dl">'</span><span class="p">;</span> <span class="c1">//b模块中也 require 了 a,但是a模块只会运行一次</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./c</span><span class="dl">'</span><span class="p">);</span> <span class="c1">//如果 require es6模块,将会自动封装成一个对象</span>
<span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./d</span><span class="dl">'</span><span class="p">);</span> <span class="c1">//es6模块(没有使用default)</span>
<span class="k">import</span> <span class="nx">modC</span> <span class="k">from</span> <span class="dl">'</span><span class="s1">./c</span><span class="dl">'</span><span class="p">;</span> <span class="c1">//标准 es6 写法</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modA</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modB</span><span class="dl">'</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modC</span><span class="dl">'</span><span class="p">,</span><span class="nx">c</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modD</span><span class="dl">'</span><span class="p">,</span><span class="nx">d</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modC</span><span class="dl">'</span><span class="p">,</span><span class="nx">modC</span><span class="p">);</span>
</code></pre></div></div>
<p>运行结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/webpack的几种引用方式.png" alt="" /></p>
阿里云OSS跨域设置
2018-12-20T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2018/12/20/阿里云OSS跨域设置
<h2 id="阿里云oss跨域设置">阿里云OSS跨域设置</h2>
<p>当使用阿里云OSS进行web端直连断点上传文件时,跨域设置投必须增加Etag,否则<code class="language-plaintext highlighter-rouge">CompleteMultipartUpload</code>阶段时,服务器将返回400(InvalidPart)</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/aliyun.oss-setting.png" alt="" /></p>
wirshark过滤
2018-12-09T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2018/12/09/wirshark过滤
<h2 id="运算符">运算符</h2>
<ul>
<li>小于: <,lt</li>
<li>小于等于: le,<=</li>
<li>大于: gt,></li>
<li>大于等于: ge,=</li>
<li>等于: eq,=</li>
<li>不等: ne,!=</li>
<li>非: not,!</li>
<li>与: and,&&</li>
<li>或: or,||</li>
</ul>
<h2 id="过滤ip">过滤IP</h2>
<ul>
<li>ip.src eq 192.168.1.107 or ip.dst eq 192.168.1.107</li>
<li>ip.addr eq 192.168.1.107 // 都能显示来源IP和目标IP</li>
</ul>
<h2 id="过滤端口">过滤端口</h2>
<ul>
<li>tcp.port eq 80 // 不管端口是来源的还是目标的都显示</li>
<li>tcp.port == 80</li>
<li>tcp.port eq 2722</li>
<li>tcp.port eq 80 or udp.port eq 80</li>
<li>tcp.dstport == 80 // 只显tcp协议的目标端口80</li>
<li>tcp.srcport == 80 // 只显tcp协议的来源端口80</li>
<li>tcp.port >= 1 and tcp.port <= 80</li>
</ul>
<h2 id="过滤协议">过滤协议</h2>
<ul>
<li>tcp</li>
<li>udp</li>
<li>arp</li>
<li>icmp</li>
<li>http</li>
<li>smtp</li>
<li>ftp</li>
<li>dns</li>
<li>msnms</li>
<li>ip</li>
<li>ssl</li>
<li>oicq</li>
<li>bootp</li>
<li>!arp 或者 not arp</li>
</ul>
<h2 id="过滤mac">过滤MAC</h2>
<ul>
<li>eth.dst == A0:00:00:04:C5:84 // 过滤目标mac</li>
<li>eth.src eq A0:00:00:04:C5:84 // 过滤来源mac</li>
<li>eth.dst==A0:00:00:04:C5:84</li>
<li>eth.dst==A0-00-00-04-C5-84</li>
<li>eth.addr eq A0:00:00:04:C5:84 // 过滤来源MAC和目标MAC都等于A0:00:00:04:C5:84的</li>
</ul>
<h2 id="包长度过滤">包长度过滤</h2>
<ul>
<li>udp.length == 26 //这个长度是指udp本身固定长度8加上udp下面那块数据包之和</li>
<li>tcp.len >= 7 //指的是ip数据包(tcp下面那块数据),不包括tcp本身</li>
<li>ip.len == 94 //除了以太网头固定长度14,其它都算是ip.len,即从ip本身到最后</li>
<li>frame.len == 119 //整个数据包长度,从eth开始到最后</li>
</ul>
<h2 id="http模式过滤">http模式过滤</h2>
<ul>
<li>http.request.method == “GET”</li>
<li>http.request.method == “POST”</li>
<li>http.request.uri == “/img/logo-edu.gif”</li>
<li>http contains “GET”</li>
<li>http contains “HTTP/1.”</li>
<li>http.request.method == “GET” && http contains “Host: “</li>
</ul>
<h2 id="tcp参数过滤">TCP参数过滤</h2>
<ul>
<li>tcp.flags //显示包含TCP标志的封包。</li>
<li>tcp.flags.syn == 0x02 //显示包含TCP SYN标志的封包。</li>
<li>tcp.window_size == 0 && tcp.flags.reset != 1</li>
</ul>
<h2 id="过滤内容">过滤内容</h2>
<p>语法:tcp[offset,n]</p>
<ul>
<li>tcp[20]表示从20开始,取1个字符</li>
<li>tcp[20:]表示从20开始,取1个字符以上</li>
<li>tcp[20:8]表示从20开始,取8个字符</li>
</ul>
<p>例:</p>
<ul>
<li>udp[8:3]==81:60:03 // 偏移8个bytes,再取3个数,是否与==后面的数据相等?</li>
<li>udp[8:1]==32 如果我猜的没有错的话,应该是udp[offset:截取个数]=nValue</li>
<li>eth.addr[0:3]==00:06:5B</li>
</ul>
<h2 id="matches">matches</h2>
<p>matches 可以使用正则匹配</p>
<p>例:</p>
<ul>
<li>http.request.full_uri matches “http://.<em>\.jpg.</em>”</li>
</ul>
<h2 id="contains">contains</h2>
<p>matches 可以用来判断是否包含某个字符串(不可以使用正则)</p>
<p>例:</p>
<ul>
<li>tcp contains “baidu”</li>
<li>ip contains “baidu”</li>
</ul>
<h2 id="让-wirshark-支持-https-包的抓取与分析">让 wirshark 支持 https 包的抓取与分析</h2>
<p>默认情况下,wirshark 是不支持 https 包的分析的,需要做如下配置:</p>
<ul>
<li>配置环境变量<code class="language-plaintext highlighter-rouge">SSLKEYLOGFILE</code>指向一个日志文件,如:<code class="language-plaintext highlighter-rouge">D:\Program Files\Wireshark\firefox_sslkey.log</code> (chrome, firfox 使用该文件记录ssl秘钥)</li>
<li>在 wirshark 配置该日志文件的路径(编辑->首选项->Protocols->ssl)</li>
</ul>
<h2 id="包数据的过滤">包数据的过滤</h2>
<p>对于 http 协议,可以使使用如下 filter 过滤:</p>
<ul>
<li>http.file_data contains “<html>” //response 包含’<html>’</li>
<li>http.request.full_uri contains “notice” //请求链接里包含 ‘notice’</li>
</ul>
<p>对于 http2 协议,可以使用如下 filter 过滤(已经配置<code class="language-plaintext highlighter-rouge">SSLKEYLOGFILE</code>):</p>
<ul>
<li>http2.data.data contains “<html>” //response 包含’<html>’</li>
<li>http2.header.value “.do” //请求数据里包含 ‘.do’</li>
</ul>
前端性能优化之-setImmediate,setTimeout,process.nextTick的区别
2018-10-12T15:45:00+00:00
https://blog.lisong.hn.cn/2018/10/12/前端性能优化之-setImmediate,setTimeout,process.nextTick的区别
<blockquote>
<p>setImmediate 和 process.nextTick 是 nodejs 中的 api,标准浏览器里是没有这两个函数,不过 ie10+ 浏览器实现了非标准的 setImmediate,其主要用来在事件循环结束后,尽快的执行其回调(延时<=2ms)。在前端开发中,应避免使用 setImmediate。</p>
</blockquote>
<p>为了实现异步执行代码,js 引擎使用了观察者来检测相应的队列是否有待执行的任务。setTimeout 采用的是类似IO观察者,setImmediate 采用的是 check 观察者,而 process.nextTick 采用的是 idle 观察者。每个事件循环都会执行一遍检测操作。这三个观察者的优先级为:<strong>idle > IO > check</strong>。</p>
<p>process.nextTick 属于 micro-task ,优先级甚至比 promise 更高。setTimeout 和 setImmediate 属于 macro-task。</p>
<p>在具体实现上,process.nextTick 的回调函数保存在一个数组中,setImmediate 的回调函数保存在普通链表中,setTimeout 的回调则保存在一颗红黑树中。</p>
<p>在行为上,process.nextTick 在每轮循环中会将数组中的回调函数全部执行完,而 setImmediate 和 setTieout 在每轮循环中执行链表中的一个回调函数。</p>
<p><strong>注意:以下的测试均在 Miscrosoft Edg 上运行</strong></p>
<p>测试1:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>test<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">setImmediate</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">setImmediate</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">setTimeout</span><span class="dl">'</span><span class="p">);</span>
<span class="p">},</span><span class="mi">6</span><span class="p">);</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>之所以 setTimeout 先运行,是因为脚步执行完后,页面需要进行首次渲染(渲染事件的优先级大于 macro-task),渲染完成后,事件循环会检测队列,由于 IO 观察者优先级高于 check观察者,所以先检测到 setTimeout 的回调(渲染花费的时间要大于6ms)。</p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/setImmediate-1.png" alt="" /></p>
<p>测试2:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>test<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">setImmediate</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">setImmediate</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">setTimeout</span><span class="dl">'</span><span class="p">);</span>
<span class="p">},</span><span class="mi">0</span><span class="p">);</span>
<span class="p">},</span><span class="mi">100</span><span class="p">);</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>事件循环结束后检查队列,由于 setTimout(0) 的计时器到期时间(>=4ms)大于 setImmediate 的计时器到期时间(<=2ms),所以 setImmediate 的回调将被先检测到。</p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/setImmediate-2.png" alt="" /></p>
<p>测试3:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">setTimeout</span><span class="dl">'</span><span class="p">);</span>
<span class="p">},</span><span class="mi">0</span><span class="p">)</span>
<span class="kd">var</span> <span class="nx">t</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="k">while</span><span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">-</span> <span class="nx">t</span><span class="o"><</span><span class="mi">100</span><span class="p">){</span>
<span class="p">}</span>
<span class="nx">setImmediate</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">setImmediate</span><span class="dl">'</span><span class="p">);</span>
<span class="p">})</span>
<span class="p">},</span><span class="mi">100</span><span class="p">);</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>由于耗时操作,事件循环结束后,setImmediate 和 setTimeout 的计时器都已过期,由于 IO 观察者优先级较高,setTimeout 回调将被先检测到。</p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/setImmediate-3.png" alt="" /></p>
JS数据结构-动态规划求LCS
2018-10-10T20:20:00+00:00
https://blog.lisong.hn.cn/js%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/2018/10/10/JS数据结构-动态规划求LCS
<blockquote>
<p>动态规划是很多算法(例如KMP算法)的基础,有很多的应用场景,其核心原理为:通过前面一个或者几个状态推算出后一个状态,往往使用迭代来求出最优解。求最长公共子串 LCS(longest common substring)是动态规划的典型应用。</p>
</blockquote>
<p>求 LCS 的普通算法:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
* @param {Array/String} 数组1
* @param {Array/String} 数组1
* @return {Array/String} 最大连续的公共子串
*/</span>
<span class="kd">function</span> <span class="nx">getLCS</span><span class="p">(</span><span class="nx">arr1</span><span class="p">,</span> <span class="nx">arr2</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">sub</span> <span class="o">=</span> <span class="nx">arr1</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="p">?</span> <span class="p">[]</span> <span class="p">:</span> <span class="dl">''</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">arr1</span><span class="p">.</span><span class="nx">length</span> <span class="o">||</span> <span class="o">!</span><span class="nx">arr2</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">sub</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">maxSize</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">preSize</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">arr1</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">preIndex</span> <span class="o">=</span> <span class="nx">i</span><span class="p">;</span>
<span class="c1">//以i为首的arr1子串与arr2中的每个子串比较</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o"><</span> <span class="nx">arr2</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">arr1</span><span class="p">[</span><span class="nx">preIndex</span><span class="p">]</span> <span class="o">==</span> <span class="nx">arr2</span><span class="p">[</span><span class="nx">j</span><span class="p">])</span> <span class="p">{</span>
<span class="nx">preIndex</span><span class="o">++</span><span class="p">;</span>
<span class="nx">preSize</span><span class="o">++</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">preSize</span> <span class="o">></span> <span class="nx">maxSize</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">maxSize</span> <span class="o">=</span> <span class="nx">preSize</span><span class="p">;</span>
<span class="nx">index</span> <span class="o">=</span> <span class="nx">j</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">preIndex</span> <span class="o">=</span> <span class="nx">i</span><span class="p">;</span>
<span class="nx">preSize</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">index</span> <span class="o">></span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">sub</span> <span class="o">=</span> <span class="nx">arr2</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">index</span> <span class="o">-</span> <span class="nx">maxSize</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">sub</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>动态规划中有三个概念:边界、最优子结构、状态转移公式。</p>
<p>对于求 LCS 的问题,设两个字符串分别为 a 和 b ,a 的长度为 m,b 的长度为 n。其状态转移公式可用如下表示:</p>
<ol>
<li><strong>dp(0,0) = 0 (a[0]!=b[0])</strong></li>
<li><strong>dp(0,0) = 1 (a[0]==b[0])</strong></li>
<li><strong>dp(i,j) = dp(i-1,j-1) + 1 (a[i] == b[j])</strong></li>
<li><strong>dp(i,j) = 0 (a[i] != b[j])</strong></li>
</ol>
<p>在这个方程中,1和2为边界,3为最优子结构。</p>
<p>动态规划求 LCS 的算法:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
* @param {Array/String} 数组1
* @param {Array/String} 数组1
* @return {Array/String} 最大连续的公共子串
*/</span>
<span class="kd">function</span> <span class="nx">getLCS</span><span class="p">(</span><span class="nx">arr1</span><span class="p">,</span> <span class="nx">arr2</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">sub</span> <span class="o">=</span> <span class="nx">arr1</span> <span class="k">instanceof</span> <span class="nb">Array</span> <span class="p">?</span> <span class="p">[]</span> <span class="p">:</span> <span class="dl">''</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">arr1</span><span class="p">.</span><span class="nx">length</span> <span class="o">||</span> <span class="o">!</span><span class="nx">arr2</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">sub</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">maxSize</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">preDp</span> <span class="o">=</span> <span class="p">[];</span>
<span class="kd">var</span> <span class="nx">dp</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">index</span> <span class="o">=</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">arr1</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">dp</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">j</span> <span class="o"><</span> <span class="nx">arr2</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">dp</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">arr1</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">==</span> <span class="nx">arr2</span><span class="p">[</span><span class="nx">j</span><span class="p">])</span> <span class="p">{</span>
<span class="nx">dp</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="nx">preDp</span><span class="p">[</span><span class="nx">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">||</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">dp</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o">></span> <span class="nx">maxSize</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">maxSize</span> <span class="o">=</span> <span class="nx">dp</span><span class="p">[</span><span class="nx">j</span><span class="p">];</span>
<span class="nx">index</span> <span class="o">=</span> <span class="nx">j</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//保存i行的结果,供i+1行使用</span>
<span class="nx">preDp</span> <span class="o">=</span> <span class="nx">dp</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">index</span> <span class="o">></span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">sub</span> <span class="o">=</span> <span class="nx">arr2</span><span class="p">.</span><span class="nx">slice</span><span class="p">(</span><span class="nx">index</span> <span class="o">-</span> <span class="nx">maxSize</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">index</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">sub</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/js-dp-lcs/tree/master/src"><strong>完整代码</strong></a></p>
JS数据结构-红黑树
2018-09-30T22:44:00+00:00
https://blog.lisong.hn.cn/js%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/2018/09/30/JS数据结构-红黑树
<blockquote>
<p>红黑是一棵特殊的平衡二叉树,其没有AVL树那么严格,其查找时间复杂的为2log<sub>2</sub>N,在实际开发中更加常用。</p>
</blockquote>
<h2 id="红黑树的特性">红黑树的特性</h2>
<ul>
<li>根节点为黑色;</li>
<li>不存在两个连续的红色节点;</li>
<li>叶子节点为NULL的黑色节点;</li>
<li>根节点到每个叶子节点所经过的黑色节点个数一致;</li>
</ul>
<h2 id="红黑树的插入">红黑树的插入</h2>
<p>当插入的节点为根节点时,直接将根节点颜色置为黑色。</p>
<p>为了减少调整的次数,插入的子节点默认置为红色,当插入的节点的父节点为黑色时候,此时没有破坏红黑树的特征,不需要调整树。</p>
<p>当插入的节点的父节点为红色时,此时需要对树进行调整,主要有以下两种大的情况:叔叔节点为红色,叔叔节点为黑色。</p>
<h3 id="叔叔节点为红色">叔叔节点为红色</h3>
<p><img src="https://blog.lisong.hn.cn/images/posts/JS数据结构/2018-09-29-JS数据结构-红黑树-insert-1.svg" alt="" /></p>
<h3 id="叔叔节点为黑色">叔叔节点为黑色</h3>
<p><img src="https://blog.lisong.hn.cn/images/posts/JS数据结构/2018-09-29-JS数据结构-红黑树-insert-2.svg" alt="" /></p>
<p>插入对应的代码:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//插入后检查并调整树</span>
<span class="nx">_proto</span><span class="p">.</span><span class="nx">_insertBalance</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">))</span> <span class="p">{</span> <span class="c1">//右子树不平衡,需要调整</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//如果左节点为红节点,不需要旋转,只需要改变颜色</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span> <span class="o">!=</span> <span class="k">this</span><span class="p">.</span><span class="nx">root</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//如果是根节点,不需要变色</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//左旋转</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_lRotate</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">//先右旋转,再左旋转</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_rlRotate</span><span class="p">(</span><span class="nx">node</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span> <span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">))</span> <span class="p">{</span> <span class="c1">//左子树不平衡,需要调整</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//如果右节点为红节点,不需要旋转,只需要改变颜色</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span> <span class="o">!=</span> <span class="k">this</span><span class="p">.</span><span class="nx">root</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//如果是根节点,不需要变色</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//左旋转</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_rRotate</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">//先左旋转,再右旋转</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_lrRotate</span><span class="p">(</span><span class="nx">node</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_setHeight</span><span class="p">(</span><span class="nx">node</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<h2 id="红黑树的删除">红黑树的删除</h2>
<p>平衡二叉树的删除和二叉排序树的删除原则一样,如果待删除的既有左子树又有右子树,则将其与对应的叶子节点(没有左子树或者没有右子树)替换位置,再删除该叶子节点。</p>
<p>如果删除的节点为红色,不用调整树,直接删除即可。如果删除的节点为黑色(根据红黑树性质,其必然没有左右子树),则需要重新调整树。下面主要讨论删除黑色子节点的情况。</p>
<h3 id="左子树缺少一个黑色节点">左子树缺少一个黑色节点</h3>
<p><img src="https://blog.lisong.hn.cn/images/posts/JS数据结构/2018-09-29-JS数据结构-红黑树-del-1.svg" alt="" /></p>
<p>调整左子树对应的代码:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//兄弟节点为红色</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_lRotate</span><span class="p">(</span><span class="nx">pNode</span><span class="p">);</span>
<span class="c1">//将兄弟节点变成黑色节点后,再平衡</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_deleteBalance</span><span class="p">(</span><span class="nx">pNode</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">))</span> <span class="p">{</span> <span class="c1">//兄弟节点的子节点为红色</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">||</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//兄弟节点的右子节点不为红色</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="c1">//先右旋转</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_rRotate</span><span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">tmp</span> <span class="o">=</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="nx">tmp</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_lRotate</span><span class="p">(</span><span class="nx">pNode</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//父节点为红色</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span> <span class="o">!=</span> <span class="k">this</span><span class="p">.</span><span class="nx">root</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">==</span> <span class="nx">pNode</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_deleteBalance</span><span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">pNode</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_deleteBalance</span><span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">pNode</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="右子树缺少一个黑色节点">右子树缺少一个黑色节点</h3>
<p>调整过程和(左子树缺少一个黑色节点)类似。</p>
<p>调整右子树对应的代码:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//兄弟节点为红色</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_rRotate</span><span class="p">(</span><span class="nx">pNode</span><span class="p">);</span>
<span class="c1">//将兄弟节点变成黑色节点后,再平衡</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_deleteBalance</span><span class="p">(</span><span class="nx">pNode</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span> <span class="o">||</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">))</span> <span class="p">{</span> <span class="c1">//兄弟节点的子节点为红色</span>
<span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">||</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//兄弟节点左子节点不为红色</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="c1">//先左旋转</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_lRotate</span><span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">tmp</span> <span class="o">=</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="nx">tmp</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_rRotate</span><span class="p">(</span><span class="nx">pNode</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span> <span class="o">==</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//父节点为红色</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">color</span> <span class="o">=</span> <span class="mi">1</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span> <span class="o">!=</span> <span class="k">this</span><span class="p">.</span><span class="nx">root</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">==</span> <span class="nx">pNode</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_deleteBalance</span><span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">pNode</span><span class="p">,</span> <span class="kc">true</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_deleteBalance</span><span class="p">(</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">pNode</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/js-rb-tree/tree/master/src"><strong>完整代码</strong></a></p>
JS数据结构-AVL平衡二叉树
2018-09-27T21:43:00+00:00
https://blog.lisong.hn.cn/js%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/2018/09/27/JS数据结构-AVL平衡二叉树 - 副本
<blockquote>
<p>平衡二叉树是一棵特殊的二叉排序树,可以快速的实现查找,其查找时间复杂的为log<sub>2</sub>N。</p>
</blockquote>
<h2 id="平衡二叉树的特性">平衡二叉树的特性</h2>
<ul>
<li>具备二叉排序树的所有特性;</li>
<li>左子树和右子树深度差的绝对值不超过1;</li>
<li>左右子树都是平衡二叉树;</li>
</ul>
<p>在插入过程中,二叉树的平衡性可能遭到破坏,这时需要对二叉树进行调整。</p>
<h2 id="ll型失衡">LL型失衡</h2>
<p>左子树高度减去右子树的高度大于1。</p>
<p><img src="https://blog.lisong.hn.cn/images/posts/JS数据结构/2018-09-27-JS数据结构-AVL平衡二叉树-LL.svg" alt="" /></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//左旋转</span>
<span class="nx">_proto</span><span class="p">.</span><span class="nx">_lRotate</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">rc</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">;</span>
<span class="nx">rc</span><span class="p">.</span><span class="nx">pNode</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">;</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">=</span> <span class="nx">rc</span><span class="p">.</span><span class="nx">lChild</span><span class="p">;</span>
<span class="nx">rc</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">rc</span><span class="p">.</span><span class="nx">lChild</span><span class="p">.</span><span class="nx">pNode</span> <span class="o">=</span> <span class="nx">node</span><span class="p">);</span>
<span class="nx">rc</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">=</span> <span class="nx">node</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span> <span class="o">==</span> <span class="k">this</span><span class="p">.</span><span class="nx">root</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">root</span> <span class="o">=</span> <span class="nx">rc</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">==</span> <span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">=</span> <span class="nx">rc</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">=</span> <span class="nx">rc</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span> <span class="o">=</span> <span class="nx">rc</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="rr型失衡">RR型失衡</h2>
<p>右子树高度减去左子树的高度大于1。</p>
<p><img src="https://blog.lisong.hn.cn/images/posts/JS数据结构/2018-09-27-JS数据结构-AVL平衡二叉树-RR.svg" alt="" /></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//右旋转</span>
<span class="nx">_proto</span><span class="p">.</span><span class="nx">_rRotate</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">lc</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">;</span>
<span class="nx">lc</span><span class="p">.</span><span class="nx">pNode</span> <span class="o">=</span> <span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">;</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">=</span> <span class="nx">lc</span><span class="p">.</span><span class="nx">rChild</span><span class="p">;</span>
<span class="nx">lc</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">lc</span><span class="p">.</span><span class="nx">rChild</span><span class="p">.</span><span class="nx">pNode</span> <span class="o">=</span> <span class="nx">node</span><span class="p">);</span>
<span class="nx">lc</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">=</span> <span class="nx">node</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span> <span class="o">==</span> <span class="k">this</span><span class="p">.</span><span class="nx">root</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">root</span> <span class="o">=</span> <span class="nx">lc</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">==</span> <span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">lChild</span> <span class="o">=</span> <span class="nx">lc</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span><span class="p">.</span><span class="nx">rChild</span> <span class="o">=</span> <span class="nx">lc</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">node</span><span class="p">.</span><span class="nx">pNode</span> <span class="o">=</span> <span class="nx">lc</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="lr型失衡">LR型失衡</h2>
<p>左子树高度减去右子树的高度大于1,并 lChild 的右子树高度大于 lChild 的左子树的高度。</p>
<p><img src="https://blog.lisong.hn.cn/images/posts/JS数据结构/2018-09-27-JS数据结构-AVL平衡二叉树-LR.svg" alt="" /></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//先右旋转,再左旋转</span>
<span class="nx">_proto</span><span class="p">.</span><span class="nx">_rlRotate</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_rRotate</span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">rChild</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_lRotate</span><span class="p">(</span><span class="nx">node</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="rl型失衡">RL型失衡</h2>
<p>右子树高度减去左子树的高度大于1,并 rChild 的左子树高度大于 rChild 的右子树的高度。</p>
<p><img src="https://blog.lisong.hn.cn/images/posts/JS数据结构/2018-09-27-JS数据结构-AVL平衡二叉树-RL.svg" alt="" /></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//先左旋转,再右旋转</span>
<span class="nx">_proto</span><span class="p">.</span><span class="nx">_lrRotate</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">node</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_lRotate</span><span class="p">(</span><span class="nx">node</span><span class="p">.</span><span class="nx">lChild</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">_rRotate</span><span class="p">(</span><span class="nx">node</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="平衡二叉树的删除">平衡二叉树的删除</h2>
<p>平衡二叉树的删除和二叉排序树的删除原则一样,如果待删除的既有左子树又有右子树,则将其与对应的叶子节点(没有左子树或者没有右子树)替换位置,再删除该叶子节点。</p>
<p>同样,平衡二叉树节点的删除也有可能导致二叉树失衡,其调整原则和插入节点时一致。</p>
<p><a href="https://github.com/wanls4583/js-avl-tree/tree/master/src"><strong>完整代码</strong></a></p>
js复制文本到剪贴板
2018-07-17T00:00:00+00:00
https://blog.lisong.hn.cn/javascript/2018/07/17/js复制文本到剪贴板
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Util</span> <span class="o">=</span> <span class="p">{</span>
<span class="c1">//获取选中的文本</span>
<span class="na">getSelectedText</span><span class="p">:</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">selection</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">document</span><span class="p">.</span><span class="nx">selection</span><span class="p">.</span><span class="nx">createRange</span><span class="p">().</span><span class="nx">text</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">getSelection</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nb">window</span><span class="p">.</span><span class="nx">getSelection</span><span class="p">().</span><span class="nx">toString</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="c1">//选中元素中的文本</span>
<span class="na">select</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">element</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">selection</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">range</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">createTextRange</span><span class="p">();</span>
<span class="nx">range</span><span class="p">.</span><span class="nx">moveToElementText</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
<span class="nx">range</span><span class="p">.</span><span class="nx">select</span><span class="p">();</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nb">window</span><span class="p">.</span><span class="nx">getSelection</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">range</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createRange</span><span class="p">();</span>
<span class="nx">range</span><span class="p">.</span><span class="nx">selectNode</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">getSelection</span><span class="p">().</span><span class="nx">removeAllRanges</span><span class="p">();</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">getSelection</span><span class="p">().</span><span class="nx">addRange</span><span class="p">(</span><span class="nx">range</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="c1">//复制文本到剪贴板</span>
<span class="na">copy</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">element</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">SPAN</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">element</span><span class="p">.</span><span class="nx">textContent</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
<span class="k">this</span><span class="p">.</span><span class="nx">select</span><span class="p">(</span><span class="nx">element</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">execCommand</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">execCommand</span><span class="p">(</span><span class="dl">'</span><span class="s1">copy</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">clipboardData</span><span class="p">.</span><span class="nx">setData</span><span class="p">(</span><span class="dl">'</span><span class="s1">text</span><span class="dl">'</span><span class="p">,</span> <span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">element</span><span class="p">.</span><span class="nx">remove</span> <span class="p">?</span> <span class="nx">element</span><span class="p">.</span><span class="nx">remove</span><span class="p">()</span> <span class="p">:</span> <span class="nx">element</span><span class="p">.</span><span class="nx">removeNode</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>需要注意的是,copy操作必须用户手动触发某个点击事件或者触摸事件才能复制成功,也就是说必须在点击或者触摸的回调事件内执行copy操作,类似 IOS 中音频播放的触发。</p>
vscode搭建mac环境下c/c++开发环境
2018-06-28T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2018/06/28/vscode搭建mac-c,c++开发环境
<h2 id="第一步">第一步</h2>
<p>安装 C/C++ 扩展</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2023-10-30-vscde搭建c,c++开发环境-1.png" alt="" /></p>
<h2 id="第二步">第二步</h2>
<p>选中项目中的<code class="language-plaintext highlighter-rouge">C</code>文件后,打开控制面板,使用<strong><em>C/C++:Edit Configurations</em></strong>命令自动生成<code class="language-plaintext highlighter-rouge">c_cpp_properties.json</code>文件</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2023-10-30-vscde搭建c,c++开发环境-2.png" alt="" /></p>
<p><strong><em>c_cpp_properties.json</em></strong>:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"configurations"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Mac"</span><span class="p">,</span><span class="w">
</span><span class="nl">"includePath"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="s2">"${workspaceFolder}/**"</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"defines"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
</span><span class="nl">"macFrameworkPath"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="s2">"/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks"</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"compilerPath"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/usr/bin/clang"</span><span class="p">,</span><span class="w">
</span><span class="nl">"cStandard"</span><span class="p">:</span><span class="w"> </span><span class="s2">"c17"</span><span class="p">,</span><span class="w">
</span><span class="nl">"cppStandard"</span><span class="p">:</span><span class="w"> </span><span class="s2">"c++17"</span><span class="p">,</span><span class="w">
</span><span class="nl">"intelliSenseMode"</span><span class="p">:</span><span class="w"> </span><span class="s2">"macos-clang-arm64"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="mi">4</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<h2 id="第三步">第三步</h2>
<p>选中项目中的<code class="language-plaintext highlighter-rouge">C</code>文件后,打开控制面板,使用<strong><em>C/C++:Add Debug Configurations</em></strong>命令自动生成<code class="language-plaintext highlighter-rouge">tasks.json</code>和<code class="language-plaintext highlighter-rouge">launch.json</code>文件</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2023-10-30-vscde搭建c,c++开发环境-3.png" alt="" /></p>
<p><code class="language-plaintext highlighter-rouge">tasks.json</code>里面包含了编译任务,<code class="language-plaintext highlighter-rouge">launch.json</code>里面则是用来启动调试。</p>
<p><strong><em>tasks.json</em></strong>:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"tasks"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"cppbuild"</span><span class="p">,</span><span class="w">
</span><span class="nl">"label"</span><span class="p">:</span><span class="w"> </span><span class="s2">"C/C++: clang build active file"</span><span class="p">,</span><span class="w">
</span><span class="nl">"command"</span><span class="p">:</span><span class="w"> </span><span class="s2">"/usr/bin/clang"</span><span class="p">,</span><span class="w">
</span><span class="nl">"args"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="s2">"-fcolor-diagnostics"</span><span class="p">,</span><span class="w">
</span><span class="s2">"-fansi-escape-codes"</span><span class="p">,</span><span class="w">
</span><span class="s2">"-g"</span><span class="p">,</span><span class="w">
</span><span class="s2">"${file}"</span><span class="p">,</span><span class="w">
</span><span class="s2">"-o"</span><span class="p">,</span><span class="w">
</span><span class="s2">"${fileDirname}/${fileBasenameNoExtension}"</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"options"</span><span class="p">:</span><span class="w"> </span><span class="p">{</span><span class="w">
</span><span class="nl">"cwd"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${fileDirname}"</span><span class="w">
</span><span class="p">},</span><span class="w">
</span><span class="nl">"problemMatcher"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="s2">"$gcc"</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"group"</span><span class="p">:</span><span class="w"> </span><span class="s2">"build"</span><span class="p">,</span><span class="w">
</span><span class="nl">"detail"</span><span class="p">:</span><span class="w"> </span><span class="s2">"Task generated by Debugger."</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.0.0"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p><strong><em>launch.js</em></strong>:</p>
<div class="language-json highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="w">
</span><span class="nl">"configurations"</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="w">
</span><span class="p">{</span><span class="w">
</span><span class="nl">"name"</span><span class="p">:</span><span class="w"> </span><span class="s2">"C/C++: clang build and debug active file"</span><span class="p">,</span><span class="w">
</span><span class="nl">"type"</span><span class="p">:</span><span class="w"> </span><span class="s2">"cppdbg"</span><span class="p">,</span><span class="w">
</span><span class="nl">"request"</span><span class="p">:</span><span class="w"> </span><span class="s2">"launch"</span><span class="p">,</span><span class="w">
</span><span class="nl">"program"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${fileDirname}/${fileBasenameNoExtension}"</span><span class="p">,</span><span class="w">
</span><span class="nl">"args"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
</span><span class="nl">"stopAtEntry"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"cwd"</span><span class="p">:</span><span class="w"> </span><span class="s2">"${fileDirname}"</span><span class="p">,</span><span class="w">
</span><span class="nl">"environment"</span><span class="p">:</span><span class="w"> </span><span class="p">[],</span><span class="w">
</span><span class="nl">"externalConsole"</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">,</span><span class="w">
</span><span class="nl">"MIMode"</span><span class="p">:</span><span class="w"> </span><span class="s2">"lldb"</span><span class="p">,</span><span class="w">
</span><span class="nl">"preLaunchTask"</span><span class="p">:</span><span class="w"> </span><span class="s2">"C/C++: clang build active file"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span><span class="p">],</span><span class="w">
</span><span class="nl">"version"</span><span class="p">:</span><span class="w"> </span><span class="s2">"2.0.0"</span><span class="w">
</span><span class="p">}</span><span class="w">
</span></code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">"preLaunchTask"</code>为启动调试时预先要处理的任务,也就是上面的编译任务,<code class="language-plaintext highlighter-rouge">"program"</code>为编译后生成的可执行文件的路径。</p>
<p><strong><em>最终项目目录结构为:</em></strong></p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2023-10-30-vscde搭建c,c++开发环境-4.png" alt="" /></p>
<h2 id="调试">调试</h2>
<p>在行号处打上断点,启动调试,程序就会在断点出停住,此时可以查看变量的值</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2023-10-30-vscde搭建c,c++开发环境-5.png" alt="" /></p>
git rebase
2018-06-28T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2018/06/28/git rebase
<p><code class="language-plaintext highlighter-rouge">git rebase commitid</code></p>
<p>该命令可以把另一个分支的最新 commit 改变为当前分支的基础。在改动中会把不一致的本分支 commit 保存,把另一个分支的 commit 加载过来,然后把之前保存的 commit 打上新的时间戳放在后面,简称“变基”。<strong>rebase 过程是与提交时间无关的</strong>。</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/git-rebase-1.png" alt="" /></p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/git-rebase-2.png" alt="" /></p>
<p>在 dev 分支执行<code class="language-plaintext highlighter-rouge">git rebase master</code></p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/git-rebase-3.png" alt="" /></p>
<p>解决完第一个冲突后<code class="language-plaintext highlighter-rouge">add</code>到暂存区</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/git-rebase-4.png" alt="" /></p>
<p><code class="language-plaintext highlighter-rouge">git rebase --continue</code>继续解决下一个冲突(总共有两个冲突)</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/git-rebase-5.png" alt="" />
<img src="https://wanls4583.github.io/images/posts/开发工具/git-rebase-6.png" alt="" /></p>
<p>最终结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/git-rebase-7.png" alt="" /></p>
<p><code class="language-plaintext highlighter-rouge">git rebase</code>不会产生新的历史记录:</p>
<embed src="https://wanls4583.github.io/images/posts/开发工具/git-rebase.svg" type="image/svg+xml" />
<p><code class="language-plaintext highlighter-rouge">61ef</code>、<code class="language-plaintext highlighter-rouge">9d36</code>分别是<code class="language-plaintext highlighter-rouge">da60</code>、<code class="language-plaintext highlighter-rouge">b590</code>rebase 后的结果</p>
vue diff算法
2018-06-25T00:00:00+00:00
https://blog.lisong.hn.cn/vue/2018/06/25/vue diff算法
<h2 id="前端中的-diff-算法">前端中的 diff 算法</h2>
<p>vue 的 diff 算法 和 react 的 diff 算法大同小异,节点的所有子节点为一层,比较只会在同层级进行(也即比较新旧节点树上相对应/相同节点的所有子节点), 不会跨层级比较。</p>
<p><img src="https://github.com/aooy/blog/blob/master/images/issues-2/diff.png?raw=true" alt="" /></p>
<h2 id="vue-diff-的实现">vue diff 的实现</h2>
<p>vue 对于同层级的比较是从两端往中间逐个比较的,也即 newStartVnode(新层未比较的第一个节点)、newEndVnode(新层未比较的最后一个节点)与 oldStartVnode(旧层未比较的第一个节点)、oldEndVnode(旧层未比较的最后一个节点)两两比较。</p>
<p>以下为 vue diff 的核心源码,完整源码可参看 <a href="https://github.com/vuejs/vue/blob/dev/src/core/vdom/patch.js">patch.js</a>。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1">//判断两个节点是否相对</span>
<span class="kd">function</span> <span class="nx">sameVnode</span> <span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">(</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">key</span> <span class="o">===</span> <span class="nx">b</span><span class="p">.</span><span class="nx">key</span> <span class="o">&&</span> <span class="p">(</span>
<span class="p">(</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">tag</span> <span class="o">===</span> <span class="nx">b</span><span class="p">.</span><span class="nx">tag</span> <span class="o">&&</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">isComment</span> <span class="o">===</span> <span class="nx">b</span><span class="p">.</span><span class="nx">isComment</span> <span class="o">&&</span>
<span class="nx">isDef</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">data</span><span class="p">)</span> <span class="o">===</span> <span class="nx">isDef</span><span class="p">(</span><span class="nx">b</span><span class="p">.</span><span class="nx">data</span><span class="p">)</span> <span class="o">&&</span>
<span class="nx">sameInputType</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span>
<span class="p">)</span> <span class="c1">//...</span>
<span class="p">)</span>
<span class="p">)</span>
<span class="p">}</span>
<span class="c1">//为 vnodes 数组创建 dom</span>
<span class="kd">function</span> <span class="nx">addVnodes</span> <span class="p">(</span><span class="nx">parentElm</span><span class="p">,</span> <span class="nx">refElm</span><span class="p">,</span> <span class="nx">vnodes</span><span class="p">,</span> <span class="nx">startIdx</span><span class="p">,</span> <span class="nx">endIdx</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(;</span> <span class="nx">startIdx</span> <span class="o"><=</span> <span class="nx">endIdx</span><span class="p">;</span> <span class="o">++</span><span class="nx">startIdx</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`create </span><span class="p">${</span><span class="nx">vnodes</span><span class="p">[</span><span class="nx">startIdx</span><span class="p">].</span><span class="nx">data</span><span class="p">.</span><span class="kd">class</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="nx">createElm</span><span class="p">(</span><span class="nx">vnodes</span><span class="p">[</span><span class="nx">startIdx</span><span class="p">],</span> <span class="nx">insertedVnodeQueue</span><span class="p">,</span> <span class="nx">parentElm</span><span class="p">,</span> <span class="nx">refElm</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">vnodes</span><span class="p">,</span> <span class="nx">startIdx</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//删除 vnodes 数组对应 的 dom</span>
<span class="kd">function</span> <span class="nx">removeVnodes</span> <span class="p">(</span><span class="nx">parentElm</span><span class="p">,</span> <span class="nx">vnodes</span><span class="p">,</span> <span class="nx">startIdx</span><span class="p">,</span> <span class="nx">endIdx</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(;</span> <span class="nx">startIdx</span> <span class="o"><=</span> <span class="nx">endIdx</span><span class="p">;</span> <span class="o">++</span><span class="nx">startIdx</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">ch</span> <span class="o">=</span> <span class="nx">vnodes</span><span class="p">[</span><span class="nx">startIdx</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isDef</span><span class="p">(</span><span class="nx">ch</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`remove </span><span class="p">${</span><span class="nx">ch</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="kd">class</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isDef</span><span class="p">(</span><span class="nx">ch</span><span class="p">.</span><span class="nx">tag</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">removeAndInvokeRemoveHook</span><span class="p">(</span><span class="nx">ch</span><span class="p">);</span>
<span class="nx">invokeDestroyHook</span><span class="p">(</span><span class="nx">ch</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">// Text node</span>
<span class="nx">removeNode</span><span class="p">(</span><span class="nx">ch</span><span class="p">.</span><span class="nx">elm</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//查找 oldCh 中是否有一个 vnode 和 node 相同,若果找到了,则返回该 vnode 的数组下标</span>
<span class="kd">function</span> <span class="nx">findIdxInOld</span> <span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">oldCh</span><span class="p">,</span> <span class="nx">start</span><span class="p">,</span> <span class="nx">end</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="nx">start</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">end</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isDef</span><span class="p">(</span><span class="nx">c</span><span class="p">)</span> <span class="o">&&</span> <span class="nx">sameVnode</span><span class="p">(</span><span class="nx">node</span><span class="p">,</span> <span class="nx">c</span><span class="p">))</span> <span class="p">{</span> <span class="k">return</span> <span class="nx">i</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//挂载 dom</span>
<span class="kd">function</span> <span class="nx">patchVnode</span> <span class="p">(</span><span class="nx">oldVnode</span><span class="p">,</span> <span class="nx">vnode</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">,</span> <span class="nx">removeOnly</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//...</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isUndef</span><span class="p">(</span><span class="nx">vnode</span><span class="p">.</span><span class="nx">text</span><span class="p">))</span> <span class="p">{</span> <span class="c1">//新的 vnode 为标签</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isDef</span><span class="p">(</span><span class="nx">oldCh</span><span class="p">)</span> <span class="o">&&</span> <span class="nx">isDef</span><span class="p">(</span><span class="nx">ch</span><span class="p">))</span> <span class="p">{</span>
<span class="c1">//新旧 vnode 都有子层,则比较所有子层中的 vnode</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">oldCh</span> <span class="o">!==</span> <span class="nx">ch</span><span class="p">)</span> <span class="p">{</span> <span class="nx">updateChildren</span><span class="p">(</span><span class="nx">elm</span><span class="p">,</span> <span class="nx">oldCh</span><span class="p">,</span> <span class="nx">ch</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">,</span> <span class="nx">removeOnly</span><span class="p">);</span> <span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">isDef</span><span class="p">(</span><span class="nx">ch</span><span class="p">))</span> <span class="p">{</span>
<span class="c1">//新的 vnode 的子层中的元素都是新增的,则直接为子层中所有 vnode 创建新的 dom</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isDef</span><span class="p">(</span><span class="nx">oldVnode</span><span class="p">.</span><span class="nx">text</span><span class="p">))</span> <span class="p">{</span> <span class="nx">nodeOps</span><span class="p">.</span><span class="nx">setTextContent</span><span class="p">(</span><span class="nx">elm</span><span class="p">,</span> <span class="dl">''</span><span class="p">);</span> <span class="p">}</span>
<span class="nx">addVnodes</span><span class="p">(</span><span class="nx">elm</span><span class="p">,</span> <span class="kc">null</span><span class="p">,</span> <span class="nx">ch</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">ch</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">isDef</span><span class="p">(</span><span class="nx">oldCh</span><span class="p">))</span> <span class="p">{</span>
<span class="c1">//新的 vnode 的子层中的元素都被删除,则直接删除该层中所有的 dom</span>
<span class="nx">removeVnodes</span><span class="p">(</span><span class="nx">elm</span><span class="p">,</span> <span class="nx">oldCh</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">oldCh</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">isDef</span><span class="p">(</span><span class="nx">oldVnode</span><span class="p">.</span><span class="nx">text</span><span class="p">))</span> <span class="p">{</span>
<span class="c1">//新的 vnode 没有text,则需要删除旧的 vnode中的 text</span>
<span class="nx">nodeOps</span><span class="p">.</span><span class="nx">setTextContent</span><span class="p">(</span><span class="nx">elm</span><span class="p">,</span> <span class="dl">''</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">oldVnode</span><span class="p">.</span><span class="nx">text</span> <span class="o">!==</span> <span class="nx">vnode</span><span class="p">.</span><span class="nx">text</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//新的 vnode 文字且与旧的 vnode 的文字不一致,则直接修改字符内容即可</span>
<span class="nx">nodeOps</span><span class="p">.</span><span class="nx">setTextContent</span><span class="p">(</span><span class="nx">elm</span><span class="p">,</span> <span class="nx">vnode</span><span class="p">.</span><span class="nx">text</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//...</span>
<span class="p">}</span>
<span class="c1">//递归比较每一层</span>
<span class="kd">function</span> <span class="nx">updateChildren</span> <span class="p">(</span><span class="nx">parentElm</span><span class="p">,</span> <span class="nx">oldCh</span><span class="p">,</span> <span class="nx">newCh</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">,</span> <span class="nx">removeOnly</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">oldStartIdx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">newStartIdx</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">oldEndIdx</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">oldStartVnode</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">oldEndVnode</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="nx">oldEndIdx</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">newEndIdx</span> <span class="o">=</span> <span class="nx">newCh</span><span class="p">.</span><span class="nx">length</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">newStartVnode</span> <span class="o">=</span> <span class="nx">newCh</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">newEndVnode</span> <span class="o">=</span> <span class="nx">newCh</span><span class="p">[</span><span class="nx">newEndIdx</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">oldKeyToIdx</span><span class="p">,</span> <span class="nx">idxInOld</span><span class="p">,</span> <span class="nx">vnodeToMove</span><span class="p">,</span> <span class="nx">refElm</span><span class="p">;</span>
<span class="c1">// removeOnly is a special flag used only by <transition-group></span>
<span class="c1">// to ensure removed elements stay in correct relative positions</span>
<span class="c1">// during leaving transitions</span>
<span class="kd">var</span> <span class="nx">canMove</span> <span class="o">=</span> <span class="o">!</span><span class="nx">removeOnly</span><span class="p">;</span>
<span class="p">{</span>
<span class="nx">checkDuplicateKeys</span><span class="p">(</span><span class="nx">newCh</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">oldStartIdx</span> <span class="o"><=</span> <span class="nx">oldEndIdx</span> <span class="o">&&</span> <span class="nx">newStartIdx</span> <span class="o"><=</span> <span class="nx">newEndIdx</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//比较一层,新层对应 newCh,旧层对应 oldCh</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isUndef</span><span class="p">(</span><span class="nx">oldStartVnode</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">oldStartVnode</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="o">++</span><span class="nx">oldStartIdx</span><span class="p">];</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">isUndef</span><span class="p">(</span><span class="nx">oldEndVnode</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">oldEndVnode</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="o">--</span><span class="nx">oldEndIdx</span><span class="p">];</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">sameVnode</span><span class="p">(</span><span class="nx">oldStartVnode</span><span class="p">,</span> <span class="nx">newStartVnode</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">patchVnode</span><span class="p">(</span><span class="nx">oldStartVnode</span><span class="p">,</span> <span class="nx">newStartVnode</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">);</span>
<span class="c1">//旧层的第一个 vnode 和新层的第一个 vnode 相等,则继续比较下一个</span>
<span class="nx">oldStartVnode</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="o">++</span><span class="nx">oldStartIdx</span><span class="p">];</span>
<span class="nx">newStartVnode</span> <span class="o">=</span> <span class="nx">newCh</span><span class="p">[</span><span class="o">++</span><span class="nx">newStartIdx</span><span class="p">];</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">sameVnode</span><span class="p">(</span><span class="nx">oldEndVnode</span><span class="p">,</span> <span class="nx">newEndVnode</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">patchVnode</span><span class="p">(</span><span class="nx">oldEndVnode</span><span class="p">,</span> <span class="nx">newEndVnode</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">);</span>
<span class="c1">//旧层的最后一个 vnode 和新层的最后一个 vnode 相等,则继续比较倒数第二个</span>
<span class="nx">oldEndVnode</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="o">--</span><span class="nx">oldEndIdx</span><span class="p">];</span>
<span class="nx">newEndVnode</span> <span class="o">=</span> <span class="nx">newCh</span><span class="p">[</span><span class="o">--</span><span class="nx">newEndIdx</span><span class="p">];</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">sameVnode</span><span class="p">(</span><span class="nx">oldStartVnode</span><span class="p">,</span> <span class="nx">newEndVnode</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">patchVnode</span><span class="p">(</span><span class="nx">oldStartVnode</span><span class="p">,</span> <span class="nx">newEndVnode</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">);</span>
<span class="c1">//旧层的第一个 vnode 和新层的最后一个 vnode 相等,则将第一个真实dom插入到该层最后一个位置</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`.</span><span class="p">${</span><span class="nx">oldStartVnode</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="kd">class</span><span class="p">}</span><span class="s2"> move to end`</span><span class="p">);</span>
<span class="nx">canMove</span> <span class="o">&&</span> <span class="nx">nodeOps</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">parentElm</span><span class="p">,</span> <span class="nx">oldStartVnode</span><span class="p">.</span><span class="nx">elm</span><span class="p">,</span> <span class="nx">nodeOps</span><span class="p">.</span><span class="nx">nextSibling</span><span class="p">(</span><span class="nx">oldEndVnode</span><span class="p">.</span><span class="nx">elm</span><span class="p">));</span>
<span class="nx">oldStartVnode</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="o">++</span><span class="nx">oldStartIdx</span><span class="p">];</span>
<span class="nx">newEndVnode</span> <span class="o">=</span> <span class="nx">newCh</span><span class="p">[</span><span class="o">--</span><span class="nx">newEndIdx</span><span class="p">];</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">sameVnode</span><span class="p">(</span><span class="nx">oldEndVnode</span><span class="p">,</span> <span class="nx">newStartVnode</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">patchVnode</span><span class="p">(</span><span class="nx">oldEndVnode</span><span class="p">,</span> <span class="nx">newStartVnode</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">);</span>
<span class="c1">//旧层的最后一个 vnode 和新层的第一个 vnode 相等,则将最后一个真实 dom 插入到该层第一个位置</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`.</span><span class="p">${</span><span class="nx">oldEndVnode</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="kd">class</span><span class="p">}</span><span class="s2"> move to start`</span><span class="p">);</span>
<span class="nx">canMove</span> <span class="o">&&</span> <span class="nx">nodeOps</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">parentElm</span><span class="p">,</span> <span class="nx">oldEndVnode</span><span class="p">.</span><span class="nx">elm</span><span class="p">,</span> <span class="nx">oldStartVnode</span><span class="p">.</span><span class="nx">elm</span><span class="p">);</span>
<span class="c1">//</span>
<span class="nx">oldEndVnode</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="o">--</span><span class="nx">oldEndIdx</span><span class="p">];</span>
<span class="nx">newStartVnode</span> <span class="o">=</span> <span class="nx">newCh</span><span class="p">[</span><span class="o">++</span><span class="nx">newStartIdx</span><span class="p">];</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">//收集旧层中含有 key 的 vnode 的数组下标</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isUndef</span><span class="p">(</span><span class="nx">oldKeyToIdx</span><span class="p">))</span> <span class="p">{</span> <span class="nx">oldKeyToIdx</span> <span class="o">=</span> <span class="nx">createKeyToOldIdx</span><span class="p">(</span><span class="nx">oldCh</span><span class="p">,</span> <span class="nx">oldStartIdx</span><span class="p">,</span> <span class="nx">oldEndIdx</span><span class="p">);</span> <span class="p">}</span>
<span class="c1">//如果新层第一个 vnode 定义了 key,则返回该 key 对应的另一个 vnode 数组下标,</span>
<span class="c1">//否则查找旧中是否有一个 vnode 和 第一个 vnode 相同,若果找到了,则返回该 vnode 的数组下标</span>
<span class="nx">idxInOld</span> <span class="o">=</span> <span class="nx">isDef</span><span class="p">(</span><span class="nx">newStartVnode</span><span class="p">.</span><span class="nx">key</span><span class="p">)</span>
<span class="p">?</span> <span class="nx">oldKeyToIdx</span><span class="p">[</span><span class="nx">newStartVnode</span><span class="p">.</span><span class="nx">key</span><span class="p">]</span>
<span class="p">:</span> <span class="nx">findIdxInOld</span><span class="p">(</span><span class="nx">newStartVnode</span><span class="p">,</span> <span class="nx">oldCh</span><span class="p">,</span> <span class="nx">oldStartIdx</span><span class="p">,</span> <span class="nx">oldEndIdx</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">isUndef</span><span class="p">(</span><span class="nx">idxInOld</span><span class="p">))</span> <span class="p">{</span> <span class="c1">//没有找到 idxInOld,说明找不到可以直接移动到该位置的 dom,需要创建新的 dom</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`create </span><span class="p">${</span><span class="nx">newStartVnode</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="kd">class</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="nx">createElm</span><span class="p">(</span><span class="nx">newStartVnode</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">,</span> <span class="nx">parentElm</span><span class="p">,</span> <span class="nx">oldStartVnode</span><span class="p">.</span><span class="nx">elm</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">newCh</span><span class="p">,</span> <span class="nx">newStartIdx</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span> <span class="c1">//找到了 idxInOld</span>
<span class="nx">vnodeToMove</span> <span class="o">=</span> <span class="nx">oldCh</span><span class="p">[</span><span class="nx">idxInOld</span><span class="p">];</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">sameVnode</span><span class="p">(</span><span class="nx">vnodeToMove</span><span class="p">,</span> <span class="nx">newStartVnode</span><span class="p">))</span> <span class="p">{</span>
<span class="nx">patchVnode</span><span class="p">(</span><span class="nx">vnodeToMove</span><span class="p">,</span> <span class="nx">newStartVnode</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">);</span>
<span class="nx">oldCh</span><span class="p">[</span><span class="nx">idxInOld</span><span class="p">]</span> <span class="o">=</span> <span class="kc">undefined</span><span class="p">;</span>
<span class="c1">//如果 idxInOld 对应的 vnode 和当前处理的新层的 vnode 是同一个,则直接移动位置即可</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`</span><span class="p">${</span><span class="nx">vnodeToMove</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="kd">class</span><span class="p">}</span><span class="s2"> insertBefore </span><span class="p">${</span><span class="nx">oldStartVnode</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="kd">class</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="nx">canMove</span> <span class="o">&&</span> <span class="nx">nodeOps</span><span class="p">.</span><span class="nx">insertBefore</span><span class="p">(</span><span class="nx">parentElm</span><span class="p">,</span> <span class="nx">vnodeToMove</span><span class="p">.</span><span class="nx">elm</span><span class="p">,</span> <span class="nx">oldStartVnode</span><span class="p">.</span><span class="nx">elm</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="c1">//虽然找到了 idxInOld,但与当前处理的新层的 vnode 的标签不一致(不同标签的 key 相互不影响),还是得创建新的 dom</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="s2">`create </span><span class="p">${</span><span class="nx">newStartVnode</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="kd">class</span><span class="p">}</span><span class="s2">`</span><span class="p">);</span>
<span class="nx">createElm</span><span class="p">(</span><span class="nx">newStartVnode</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">,</span> <span class="nx">parentElm</span><span class="p">,</span> <span class="nx">oldStartVnode</span><span class="p">.</span><span class="nx">elm</span><span class="p">,</span> <span class="kc">false</span><span class="p">,</span> <span class="nx">newCh</span><span class="p">,</span> <span class="nx">newStartIdx</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//继续比较下一个</span>
<span class="nx">newStartVnode</span> <span class="o">=</span> <span class="nx">newCh</span><span class="p">[</span><span class="o">++</span><span class="nx">newStartIdx</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">oldStartIdx</span> <span class="o">></span> <span class="nx">oldEndIdx</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">refElm</span> <span class="o">=</span> <span class="nx">isUndef</span><span class="p">(</span><span class="nx">newCh</span><span class="p">[</span><span class="nx">newEndIdx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">])</span> <span class="p">?</span> <span class="kc">null</span> <span class="p">:</span> <span class="nx">newCh</span><span class="p">[</span><span class="nx">newEndIdx</span> <span class="o">+</span> <span class="mi">1</span><span class="p">].</span><span class="nx">elm</span><span class="p">;</span>
<span class="c1">//如果新层中还有未比较的 vnode(newStartIdx——newEndIdx),说明都是新增的,需要为这些 vnode 创新新的 dom</span>
<span class="nx">addVnodes</span><span class="p">(</span><span class="nx">parentElm</span><span class="p">,</span> <span class="nx">refElm</span><span class="p">,</span> <span class="nx">newCh</span><span class="p">,</span> <span class="nx">newStartIdx</span><span class="p">,</span> <span class="nx">newEndIdx</span><span class="p">,</span> <span class="nx">insertedVnodeQueue</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="k">if</span> <span class="p">(</span><span class="nx">newStartIdx</span> <span class="o">></span> <span class="nx">newEndIdx</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//如果旧层中还有未比较的 vnode(oldStartIdx——oldEndIdx),说明这些 vnode 都已经删除,需要删除对应的 dom</span>
<span class="nx">removeVnodes</span><span class="p">(</span><span class="nx">parentElm</span><span class="p">,</span> <span class="nx">oldCh</span><span class="p">,</span> <span class="nx">oldStartIdx</span><span class="p">,</span> <span class="nx">oldEndIdx</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="实例分析">实例分析</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>demo<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"vue.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"vapp"</span><span class="nt">></div></span>
<span class="nt"></body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">vm</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">.vapp</span><span class="dl">'</span><span class="p">,</span> <span class="c1">//此时el.outerHTML为待编译的模板</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span>
<span class="na">tree</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">methods</span><span class="p">:{</span>
<span class="nx">chang</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">tree</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">render</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">createElement</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">wrap</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">tree</span> <span class="o">==</span> <span class="mi">1</span><span class="p">){</span>
<span class="nx">wrap</span> <span class="o">=</span> <span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">wrap</span><span class="dl">'</span><span class="p">},[</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">span</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">s1</span><span class="dl">'</span><span class="p">}),</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">p</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">p1</span><span class="dl">'</span><span class="p">}),</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">a</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">a1</span><span class="dl">'</span><span class="p">}),</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">b</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">b1</span><span class="dl">'</span><span class="p">}),</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">d1</span><span class="dl">'</span><span class="p">}),</span>
<span class="p">])</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nx">wrap</span> <span class="o">=</span> <span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">wrap</span><span class="dl">'</span><span class="p">},[</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">d1</span><span class="dl">'</span><span class="p">}),</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">p</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">p1</span><span class="dl">'</span><span class="p">}),</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">a</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">a1</span><span class="dl">'</span><span class="p">,</span> <span class="na">key</span><span class="p">:</span> <span class="dl">'</span><span class="s1">a1</span><span class="dl">'</span><span class="p">}),</span>
<span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">span</span><span class="dl">'</span><span class="p">,{</span><span class="na">class</span><span class="p">:</span><span class="dl">'</span><span class="s1">s1</span><span class="dl">'</span><span class="p">}),</span>
<span class="p">])</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">wrap</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="nt"></script></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/vue/vue-diff/">代码</a></p>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/vue/vue-diff-1.png" alt="" /></p>
<h3 id="图解过程">图解过程</h3>
<embed src="https://wanls4583.github.io/images/posts/vue/vue-diff-2.svg" type="image/svg+xml" />
xss攻击
2018-06-22T00:00:00+00:00
https://blog.lisong.hn.cn/web%E5%AE%89%E5%85%A8/2018/06/22/xss攻击
<blockquote>
<p>跨站脚本攻击(Cross Site Scripting)本来的缩写为CSS,为了与层叠样式表(Cascading Style Sheets,CSS)的缩写进行区分,将跨站脚本攻击缩写为XSS。XSS 是一种经常出现在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。攻击者利用XSS漏洞躲避访问控制——例如同源策略(same origin policy)。</p>
</blockquote>
<h2 id="xss-攻击">XSS 攻击</h2>
<p>XSS 攻击通常分为两种:</p>
<ul>
<li>反射型</li>
<li>存储型</li>
</ul>
<p>反射型即攻击脚本不需要存储,攻击脚本直接添加到 URL 参数里,未做 XSS 防范的服务器会解析参数并返回含有攻击脚本的页面给用户。</p>
<p>index.js</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">express</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">express</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">router</span> <span class="o">=</span> <span class="nx">express</span><span class="p">.</span><span class="nx">Router</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">comment</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="nx">router</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="dl">'</span><span class="s1">index</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">router</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/xss1</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">xss</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">query</span><span class="p">.</span><span class="nx">xss</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="dl">'</span><span class="s1">index</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="na">xss</span><span class="p">:</span> <span class="nx">xss</span> <span class="p">});</span>
<span class="p">});</span>
<span class="nx">router</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/xss2</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">xss</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">query</span><span class="p">.</span><span class="nx">xss</span>
<span class="nx">res</span><span class="p">.</span><span class="kd">set</span><span class="p">(</span><span class="dl">'</span><span class="s1">X-XSS-Protection</span><span class="dl">'</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span> <span class="c1">// 关闭浏览器XSS拦截</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="dl">'</span><span class="s1">index</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span> <span class="na">xss</span><span class="p">:</span> <span class="nx">xss</span> <span class="p">});</span>
<span class="p">});</span>
<span class="nx">router</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/add</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">comment</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">body</span><span class="p">.</span><span class="nx">comment</span><span class="p">;</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="dl">'</span><span class="s1">index</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">router</span><span class="p">.</span><span class="kd">get</span><span class="p">(</span><span class="dl">'</span><span class="s1">/get</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">,</span> <span class="nx">next</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">render</span><span class="p">(</span><span class="dl">'</span><span class="s1">index</span><span class="dl">'</span><span class="p">,{</span> <span class="na">comment</span><span class="p">:</span> <span class="nx">comment</span> <span class="p">});</span>
<span class="p">});</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">router</span><span class="p">;</span>
</code></pre></div></div>
<p>index.jade</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>extends layout
block content
h1 xss demo
//-'!='代表不转义
p!= xss
form(action="/add", method="post")
textarea(name="comment",rows=10,cols=50)
<br>
input(type="submit" value="提交评论")
<br>
p
a(href="/get") 获取评论
p!= comment
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/web安全/xss/">完整示例代码</a></p>
<p>运行 express 并打开连接 <code class="language-plaintext highlighter-rouge">http://localhost:3000/xss1?xss=<img src='null' onerror='alert(1)'></code></p>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/web安全/xss攻击-1.png" alt="" /></p>
<p>可以看到,默认情况下,浏览器会拦截反射型 XSS 攻击,浏览器会判断待执行的脚本代码是否存在于浏览器的 URL 中,如果是,就不会执行,当然,可以通过设置 Header 强制执行。</p>
<p>运行<code class="language-plaintext highlighter-rouge">http://localhost:3000/xss2?xss=<img src='null' onerror='alert(1)'></code></p>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/web安全/xss攻击-2.png" alt="" /></p>
<p><img src="https://wanls4583.github.io/images/posts/web安全/xss攻击-3.png" alt="" /></p>
<p>以上是简单的反射型 XSS 攻击示例,在实际情况下,黑客会在攻击脚本里插入获取用户 cookie 的代码,获取成功后再将 cookie 信息通过链接发送到目标服务器。用户只要点击了该带有 XSS 攻击的链接,就有可能泄露自己的信息。</p>
<p>存储型 XSS 攻击一般需要服务器将黑客注入的脚本存储到服务器上,因为攻击脚本不在 URL 里,浏览器是无法拦截的,这种情况,只有在服务器端做防范。</p>
<p>打开连接 <code class="language-plaintext highlighter-rouge">http://localhost:3000/</code></p>
<p><img src="https://wanls4583.github.io/images/posts/web安全/xss攻击-4.png" alt="" /></p>
<p>输入攻击脚本,点击添加按钮,然后再点击获取评论。此时,攻击脚本就执行了。</p>
<p><img src="https://wanls4583.github.io/images/posts/web安全/xss攻击-5.png" alt="" /></p>
<h2 id="xss-防范">XSS 防范</h2>
<p>明白原理,要防范 XSS 攻击就简单多了,防范主要是在后端进行,一般有如下几种方法:</p>
<ul>
<li>将页面提交的内容进行转义。</li>
<li>如果需要处理标签,则将 script、link、style、iframe、frame 等标签过滤掉,另外 onerror、onclick 等事件属性也需要过滤掉。</li>
</ul>
webkit学习笔记-(8)硬件加速机制
2018-06-15T00:00:00+00:00
https://blog.lisong.hn.cn/webkit/2018/06/15/webkit学习笔记-(8)硬件加速机制
<h2 id="硬件加速基础">硬件加速基础</h2>
<p>对于 GPU 绘图而言,通常不像软件渲染那样只是计算其中更新的区域,一旦有更新请求,如果没有分层,引擎可能需要重新绘制所有的区域,因为计算更新部分对 GPU 来说可能耗费更多的时间。当网页分层以后,GPU 渲染只需要绘制对应的 RenderLyaer 对象的所有内容(对于 TileLayer 不是这样的情况),并将它们和之前的层合成起来即可。</p>
<p>硬件渲染机制在 RenderLayer 树建立之后需要做三件事来完成之后的网页渲染:</p>
<ul>
<li>将某些不满足条件的 RenderLayer 对象组合在一起,形成一个有后端存储的新层(合成层,Compositing Layer),用于之后的合成。对于一个 RenderLayer 对象,如果它没有后端存储的新层,那么就用它的父亲所使用的合成层。</li>
<li>将每个合成层包含的 RenderLayer 内容绘制在合成层的后端存储中,这里的绘制可以是软件绘制也可以是硬件绘制。</li>
<li>使用合成器将多个合成层按照这些层的前后顺序、合成层的 3D 变形等设置而合成最终图形。</li>
</ul>
<p>如果一个 RenderLayer 对象被 Webkit 依照一定规则创建了后端存储,那么该 RenderLayer 被称为合成层。每个合成层都有一个 RenderLayerBacking,RenderLay erBacking 负责管理 RenderLyaer 所需要的所有后端存储。</p>
<p>如果一个 RenderLayer 对象具有一下的特征之一,那么它就是合成层:</p>
<ul>
<li>RenderLayer 具有 CSS 3D 属性或者 CSS 透视效果。</li>
<li>RenderLayer 包含的 RenderObject 节点表示的是“video”元素。</li>
<li>RenderLayer 包含的 RenderObject 节点表示的是“canvas”元素。</li>
<li>RenderLayer 使用了 CSS 透明效果的动画或者 CSS 变换的动画。</li>
<li>RenderLayer 使用了硬件加速的 CSS Filter 技术。</li>
<li>RenderLayer 使用了裁剪(Clip)或者反射(Reflection)属性,并且它的后端包括一个合成层。</li>
<li>RenderLayer 有一个 Z 坐标比自己小的兄弟节点,且该节点是一个合成层。</li>
</ul>
<p>RenderLayerBacking 包含的各种 GraphicsLayer(存储空间)对象层:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/硬件加速机制-1.png" alt="" /></p>
<p>为什么 RednerLayerBacking 对象需要这么多层呢?原因有很多,例如 Webkit 需要将滚动条独立开来称为一个层,需要两个层来表示 RenderLayer 对应的 Z 坐标和为正数和 Z 坐标为负数的子女,需要为滚动内容建立新层,还可能需要裁剪层和反射层。</p>
<p>每个 RenderView(Document)对象包含一个 RenderLayerCompositor 对象,这个对象仅在硬件加速机制下才会被创建,用来管理所有的合成层,计算和决定哪些 RenderLayer 对象是合成层,而且需要为这些合成层创建 GraphicsLayer 对象。其本身类似一个 RenderLayerBacking 对象,也包含一些 GraphicsLayer 对象,这些 GraphicsLayer 对象对应的是整个网页所需要的后端存储。</p>
<p>对于 canvas 元素的合成层,其内容由视频解码器来绘制,而后通过定时器或者其他机制来告诉 Webkit 该层内容已经发送更改,需要重新合成。</p>
<p>Webkit 中的 3D 图形上下文主要是提供一组抽象接口,这一层抽象能够将 Webkit 各个移植的不同部分隐藏起来,WebCore 只是使用统一的抽象接口。</p>
<h2 id="chromium-的硬件加速机制">Chromium 的硬件加速机制</h2>
<p>在 chromium 中,所有使用 GPU 硬件加速的操作都是由一个进程(GPU 进程)负责完成的,这其中包括使用 GPU 硬件来进行绘图和合成。Chromium 是多进程架构,每个网页的 Render 进程都是将 3D 绘图操作和合成操作通过 IPC 传递给 GPU 进程,由它来统一调度并执行。在 Chrome 的 Android 版本中,GPU 进程并不存在,Chrome 是将 GPU 的所有工作放在 Browser 进程中的一个线程来完成。</p>
<p>和软件渲染不同,GPU 进程最终绘制结果不再像软件渲染那样通过共享内存传递给 Browser 进程,而是直接将页面的内容绘制在浏览器的标签窗口内。</p>
<h3 id="chromium-合成器chromium-compositor">Chromium 合成器(Chromium Compositor)</h3>
<p>Webkit 对合成层的各种设置,最后都是使用 Layer 树来表示,每个 Layer 节点包含 3D 变形、裁剪等属性,但是 Chromium 将这些属性应用到后端存储并合成这一过程并不是在 Layer 树中进行,而是将这些功能委托给 LayerImpl 树来完成,两者之间通过代理来同步,代理的作用是协调和同步两者之间的这些操作。</p>
<p>合成器的表示和实现分离架构:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/硬件加速机制-2.png" alt="" /></p>
<p>实现部分作为单独的一个线程是在 Render 进程中用来合成网页的,通常也称为合成器线程。</p>
<p>合成器的组成:</p>
<ul>
<li>事件处理部分。主要是接收 Webkit 或者其他的用户事件,例如网页滚动、放大缩小等事件,这些事件会请求合成器重新绘制一个合成层,然后合成器再合成这些层的绘制结果。</li>
<li>合成层的表示和实现。主要定义各种类型的合成层,包括它们的位置、滚动、位置、颜色等属性。</li>
<li>合成层组成两种类型的树,以及它们之间的同步等机制。</li>
<li>合成调度器:用来调度来自用户的请求,它包括一个状态用于调度当前队列中需要执行的请求,目的是协调合成层的绘制和合成、树的同步等操作。</li>
<li>合成器的输出结果。在 Chromium 合成器中,结果可以是一个 GPU Surface 或者是一个 CPU 的存储空间。</li>
<li>各种后端存储等资源。</li>
<li>支持动画和 3D 变形这些功能所需要的基础设施。</li>
</ul>
<p>合成器的 Layer 类和它的子类:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/硬件加速机制-3.png" alt="" /></p>
<p>TileLayer 是一个中间类,它被 ContentLayer 类和 ImageLayer 类继承,它的含义是一个层的后端存储被分割成瓦片状(Tiles),由多个小后端存储共同存储而成。每个瓦片可以理解为 OpenGL 中的一个纹理对象,合成层的结果被分开存储在这些瓦片中。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/硬件加速机制-4.png" alt="" /></p>
<p>ContentLayer 表示合成层使用 Skia 画布将内容绘制到结果中,对应网页中就是常见的 HTML 元素,例如 DOM 树中的 html、div 等所在的层。ImageLayer 表示图片所在的层,如果一个合成层仅仅包含一个图片,那么该图片也会使用瓦片存储技术。</p>
<p>使用瓦片存储的原因:</p>
<ul>
<li>DOM 树中的 html 元素所在的层可能会比较大,因为网页的高度很大,如果只是一个后端存储的话,那么需要一个很大的纹理对象,但是实际的 GPU 硬件只支持有限的纹理大小。</li>
<li>在一个比较大的合成层中,可能只是其中一部分发生变化,如果重新绘制整个层,会产生额外的开销,使用瓦片化的后端存储,就只需要重绘一些存在更新的瓦片。</li>
<li>当层发生滚动的时候,一些瓦片可能不再需要,然后 Webkit 需要一些新的瓦片来绘制新的区域,这些大小相同的后端存储很容易重复利用。</li>
</ul>
<p>合成器内部是一个循环系统,状态机计算出下一个任务,调度器获得任务并执行该任务,然后接着计算下一个任务,如此循环,知道空闲为止。</p>
<p>合成工作主要有四个步骤,这些步骤都是由调度器调度:</p>
<ol>
<li>创建输出结果的目标对象“Surface”,也就是合成结果的存储空间。</li>
<li>开始一个新的帧(Begin Frame),包括计算滚动和缩放大小、动画计算、重新计算网页的布局、绘制各个合成层等。</li>
<li>将 Layer 树中包含的这些变动同步到 LayerImpl 树中。</li>
<li>合成 LayerImpl 树中各个层并交换前后帧缓冲区,完成一帧的绘制和显示动作。</li>
</ol>
<p>在这四个步骤中,步骤1只是在最开始的时候调用,而且是一次性的动作。当后面网页出现动画或者 JavaScript 代码修改 CSS 样式和 DOM 等情况的时候,一般会执行后面三个步骤,当然也可能只需要步骤4。</p>
<p>每个网页可能需要一个合成器,网页中的 iframe 也需要一个合成器,整个网页同浏览器的合成也需要一个合成器,这些合成器构成一个层次化的的合成器结构。根合成器是浏览器最高层的合成器,该合成器负责网页和浏览器用户界面的合成。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/硬件加速机制-5.png" alt="" /></p>
<h3 id="减少重绘">减少重绘</h3>
<p>计算布局和绘图比较费时间,而合成需要的时间相对少一些。</p>
<p>使用 CSS 3D 变形技术,它能够让浏览器仅仅使用合成器来合成所有的层就可以达到动画效果,而不是通过重新设置其他 CSS 属性并触发计算布局、重新绘制图形、重新合成所有层这一非常复杂的过程。Webkit 不需要大量的布局计算,不需要重新绘制,只需要修改合成时候的属性即可。当合成器需要合成的时候,每个合成层都可以设置自己的 3D 变形属性,这些属性仅仅改变合成层的变化参数,而不需要布局计算和绘图操作,可以极大地节省时间。</p>
<h2 id="其他硬件加速模块">其他硬件加速模块</h2>
<p>2D 绘图本身是使用 2D 的图形上下文,而且一般使用软件方式来绘制它们,也就是光栅化(Rasterize)的方法。但是,其实这些 2D 绘图操作也可以使用 GPU 也就是 3D 绘图来完成,使用 GPU 来绘制 2D 图形的方法称为 2D 图形的硬件加速机制。目前 2D 图形的硬件加速有两种应用场景,第一种是网页基本元素的绘制,针对的层次类型为 ContentLayer,它的后端存储是一个 2D 的画布对象;第二种是 canvas 元素,用来绘制 2D 图形。</p>
<p>一个“canvas”元素的对象只能绘制 2D 图形和 3D 图形中的一种,不能够同时绘制这两者。canvas 2D 可以使用软件方法来绘制,也可以使用 GPU 来绘制,如果使用硬件加速机制的话,Chromium 会创建一个 SkDeferredCanvas 对象,该对象使用延迟技术,会先保存多个 2D 图形操作,当 Chromium 需要绘制一个新的帧的时候,Skia 图形库才会一次性提交并绘制这些缓存的操作。</p>
webkit学习笔记-(7)渲染基础
2018-06-14T00:00:00+00:00
https://blog.lisong.hn.cn/webkit/2018/06/14/webkit学习笔记-(7)渲染基础
<h2 id="renderobject-树">RenderObject 树</h2>
<p>对于可视节点(head、meta 等为非可视节点),Webkit 会为它们建立相应的 RenderObject 对象,这个对象保存了为绘制 DOM 节点所需要的各种信息。这些 RenderObject 对象同 DOM 节点一样,也会构成一棵树,称为 RenderObject 树。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/渲染基础-1.png" alt="" /></p>
<p>每个 DOM 对象都会递归调用 attach 函数,该函数检查 Element 对象是否需要创建 RenderObject,如果需要,则调用 NodeRenderingContext 类来创建相应的 RenderObject 节点。</p>
<p>RenderObject 基类和它的主要子类:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/渲染基础-2.png" alt="" /></p>
<p>Webkit 在某些情况下需要建立匿名的 RenderObject,因为 RenderBlock 的子女必须都是内嵌的元素或者都是非内嵌的元素。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nt">video</span><span class="o">,</span><span class="nt">div</span><span class="o">,</span><span class="nt">canvas</span><span class="p">{</span>
<span class="nl">-webkit-transform</span><span class="p">:</span> <span class="n">rotateY</span><span class="p">(</span><span class="m">30deg</span><span class="p">)</span> <span class="n">rotateX</span><span class="p">(</span><span class="m">-45deg</span><span class="p">);</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><video</span> <span class="na">src=</span><span class="s">"avideo.mp4"</span><span class="nt">></video></span>
<span class="nt"><div></span>
<span class="nt"><canvas</span> <span class="na">id=</span><span class="s">"a2d"</span><span class="nt">></canvas></span>
<span class="nt"><canvas</span> <span class="na">id=</span><span class="s">"a3d"</span><span class="nt">></canvas></span>
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">size</span> <span class="o">=</span> <span class="mi">300</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">a2dCtx</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">a2d</span><span class="dl">'</span><span class="p">).</span><span class="nx">getContext</span><span class="p">(</span><span class="dl">'</span><span class="s1">2d</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">a2dCtx</span><span class="p">.</span><span class="nx">canvas</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="nx">size</span><span class="p">;</span>
<span class="nx">a2dCtx</span><span class="p">.</span><span class="nx">canvas</span><span class="p">.</span><span class="nx">height</span> <span class="o">=</span> <span class="nx">size</span><span class="p">;</span>
<span class="nx">a2dCtx</span><span class="p">.</span><span class="nx">fillRect</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">200</span><span class="p">,</span><span class="mi">200</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">a3dCtx</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">a2d</span><span class="dl">'</span><span class="p">).</span><span class="nx">getContext</span><span class="p">(</span><span class="dl">'</span><span class="s1">2d</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">a3dCtx</span><span class="p">.</span><span class="nx">canvas</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="nx">size</span><span class="p">;</span>
<span class="nx">a3dCtx</span><span class="p">.</span><span class="nx">canvas</span><span class="p">.</span><span class="nx">height</span> <span class="o">=</span> <span class="nx">size</span><span class="p">;</span>
<span class="nx">a3dCtx</span><span class="p">.</span><span class="nx">clearColor</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mf">192.0</span><span class="o">/</span><span class="mf">255.0</span><span class="p">,</span><span class="mf">192.0</span><span class="o">/</span><span class="mf">255.0</span><span class="p">,</span><span class="mf">80.0</span><span class="o">/</span><span class="mf">255.0</span><span class="p">);</span>
<span class="nx">a3dCtx</span><span class="p">.</span><span class="nx">clear</span><span class="p">(</span><span class="nx">a3dCtx</span><span class="p">.</span><span class="nx">COLOR_BUFFER_BIT</span><span class="p">);</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>DOM 树节点和 RenderObject 树的对应关系:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/渲染基础-3.png" alt="" /></p>
<h2 id="网页层次和-renderlayer-树">网页层次和 RenderLayer 树</h2>
<p>Webkit 会为网页的层次创建相应的 RenderLayer 对象,当某些类型的 RenderObject 的节点或者具有某些 CSS 样式的 RenderObject 节点出现的时候,Webkit 会这些节点创建 RenderLayer 对象。一般来说,某个 RenderObject 节点的后代都属于该节点,除非 Webkit 根据规则为某个后代节点创建了一个新的 RenderLayer 对象。</p>
<p>RenderLayer 树是基于 RenderObject 树建立起来的一棵新树。RenderObject 节点和 RenderLayer 节点不是一一对应关系,而是一对多的关系。下面这些情况会建立新的 RenderLayer 节点:</p>
<ul>
<li>DOM 树的 Document 节点对应的 RenderView 节点。</li>
<li>DOM 树中的 Document 的子女节点,也即 HTM 对应的 RenderOject 节点。</li>
<li>显示的指定 CSS 位置的 RenderObject 节点(position:absolute等)。</li>
<li>有透明效果的 RenderObject 节点。</li>
<li>节点有溢出(Overflow)、alpha 或者反射等效果的 RenderObject 节点。</li>
<li>使用 Canvas 2D 和 3D 技术的 RenderObject 节点。</li>
<li>Video 节点对应的 RenderObject 节点。</li>
</ul>
<p>除了 RenderLyaer 树的根节点,一个 RenderLayer 节点的父节点就是该 RenderLayer 节点对应的 RenderObject 节点的祖先链中最近的祖先。</p>
<p>每个 RenderLyaer 节点包含的 RenderObject 节点其实是一棵 RenderObject 子树。<strong>理想情况下</strong>,每个 RenderLayer 对象都会有一个<strong>后端类</strong>,该后端类用来存储该 RenderLayer 对象绘制的结果。</p>
<p>RenderObject 树和 RenderLayer 树的对应关系:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/渲染基础-4.png" alt="" /></p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/渲染基础-5.png" alt="" /></p>
<p>“layer at(x,x)”表示的是不同 RenderLayer 节点,下面所有的 RenderObject 子类对象均属于该 RenderObject 对象。“canvas”元素并没有在第二个 layer 中,虽然该元素仍然是 RenderBody 节点的子女。第二 layer 包含一个匿名的 RenderBlock 节点。第三个 RenderLyaer 对象是在 Webkit 执行 JavasSript 代码时才被创建的,因为 Webkit 需要检查出 JavaScript 代码是否为“canvas”确实创建了绘图上下文,而不是在遇到“canvas”元素时就创建新的 RenderLayer 对象。</p>
<h2 id="渲染方式">渲染方式</h2>
<p>在 Wibkit 中,绘图操作被定义了一个抽象层,称为绘图上下文。绘图上下文可分为两种类型,第一种是用来绘制 2D 图形的上下文,称之为 2D 绘图上下文(GraphicsContext);第二种是绘制 3D 图形的上下文,称之为 3D 绘图上下文(GraphicsContext3D)。这两种上下文都是抽象类,也就是说它们只提供接口,因为 Webkit 需要支持不同的移植。而这两个抽象基类的具体绘制则由不同的移植提供不同的实现。</p>
<p>PlatfromCraphicsContext 类和 PlatfromCraphicsContext3D 类是两个表示上下文的类,Webkit 通过 C 语言的 typeof 来将每个不同移植的类重命名成 PlatfromCraphicsContext 和 PlatfromCraphicsContext3D。</p>
<p>每个 RenderLyaer 对象可以被想象成图像中的一个层,各个层一同构成了一个图像。在渲染的过程中,浏览器也可以作同样的理解。每个层对应网页中的一个或者一些可视元素,这些元素的都绘制内容到该层上。如果绘图操作使用 CPU 来完成,那么称之为软件绘图。如果绘图操作由 GPU 来完成,则称之为 GPU 硬件加速绘图。理想情况下,每个层都有个绘制的存储区域,这个存储区域用来保存绘图的结果。最后,需要将这些层的内容合并到同一个图像之中,称之为合成(Composit),使用了合成技术的渲染称之为合成化渲染。</p>
<p>渲染方式一般分为三种:</p>
<ul>
<li>软件渲染:使用 CPU 来绘制每一层</li>
<li>硬件渲染:使用 GPU 来绘制每一层</li>
<li>合成化渲染:使用 CPU 绘制一些层,使用 GPU 绘制另一些层</li>
</ul>
<p><img src="http://wanls4583.github.io/images/posts/webkit/渲染基础-6.png" alt="" /></p>
<p>在软件渲染的机制中,通常渲染的结果就是一个位图(Bitmap),绘制每一层的时候都使用该位图,区别在于绘制的位置可能不一样,当然每一层都是按照顺序从后到前的顺序,所以软件渲染没有合成阶段。</p>
<p>硬件渲染和合成化渲染都包含了合成的工作,合成的工作都是由 GPU 来做,称之为硬件加速合成(Accelerated Compositing)。对于使用 CPU 来绘制的层,该层首先保存在 CPU 中,之后被传输到 GPU 内存中,用于之后的合成。</p>
<h2 id="软件渲染过程">软件渲染过程</h2>
<p>对于每个 RenderObject 对象,需要三个阶段来绘制自己,第一阶段是绘制该层的背景和边框,第二阶段是绘制浮动内容,第三阶段是绘制前景(子元素)、轮廓(outline)。子元素的绘制同样遵循该机制。</p>
<p>Webkit 第一次绘制网页的时候,Webkit 绘制的区域等同于可是区域的大小。在这之后,Webkit 只是首先计算需要更新的区域,然后绘制和这些区域有交集的 RenderObject 节点。这也就是说,如果更新区域跟某个 RenderLayer 节点有交集,Webkit 会继续查找 RenderLyaer 树中包含的 RenderObject 子树中的特定一个或一些节点,而不是绘制整个 RenderLayer 对应的 RenderObject 子树。如果该层和更新区域重叠,则需要绘制该层所有的 RenderObject。</p>
<p>在 Render 进程中,Skia Canvas 把内容绘制到位图中,该位图的后端即是共享的内存 CPU。当 Borwser 进程收到 Render 进程关于绘制完成的通知消息,Browser 进程会把共享内存复制到 BackingStrore 对象中,然后释放共享内存。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/渲染基础-7.png" alt="" /></p>
<p>一个多进程的软件渲染过程大致是这样的:RenderWidget类接受到更新请求时,Chrominum 创建一个共享内存区域。然后 Chrominum 创建 Skia 的 SkCanvas 对象,并且 RenderWidget 会把实际绘制任务派发给 RenderObject 树。Webkit 负责遍历 RenderObject 树,每个 RenderObject 节点根据需要来绘制自己和子女到目标存储空间,也就是 SkCanvas 对象对应的共享内存的位图中。最后,RenderWidgetHost 类把位图复制到 BackingStore 对象的相应区域中,并调用“paint”来把结果绘制到窗口中。</p>
JS数据结构-KMP算法
2018-06-12T22:07:00+00:00
https://blog.lisong.hn.cn/js%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/2018/06/12/JS数据结构-KMP算法
<blockquote>
<p>KMP 算法核心思想为:通过为模式串建立失败链接,使主串在匹配时不需要回溯索引。</p>
</blockquote>
<p><img src="https://wanls4583.github.io/images/posts/JS数据结构/2018-06-12-JS数据结构-KMP算法-1.png" alt="" /></p>
<p>T 为主串,P 为模式。当 P 在 Pn 匹配失败的时候,此时 P1 需要从 T2…Tn 范围内重新开始匹配,假设匹配了 <code class="language-plaintext highlighter-rouge">Xn-k,Xn-k+1...Xn-1</code>,则此时 <code class="language-plaintext highlighter-rouge">Xn-k,Xn-k+1...Xn-1 == Y1,Y2...Yk</code>,则必然有 <code class="language-plaintext highlighter-rouge">Zn-k,Zn-k+1...Zn-1 == Y1,Y2...Yk</code>。X1 的位置并不一定等于 T2,根据此原理,当模式 P 在 n 位置匹配失败的时候,应该使用 Yk+1 位置继续匹配,而主串 T 不需要移动位置。</p>
<p>KMP算法的核心即计算 Yk+1 的值,此值为下标 n 的失败链接值。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">String</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">searchStr</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">p</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="nx">j</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">flink</span> <span class="o">=</span> <span class="nx">getFlink</span><span class="p">(</span><span class="nx">p</span><span class="p">);</span>
<span class="k">while</span><span class="p">(</span> <span class="nx">i</span> <span class="o"><</span> <span class="k">this</span><span class="p">.</span><span class="nx">length</span> <span class="o">&&</span> <span class="nx">j</span><span class="o"><</span><span class="nx">p</span><span class="p">.</span><span class="nx">length</span><span class="p">){</span>
<span class="c1">//如果字符相等,或者是模式的第一个字符,主串和模式都应该向后移动一个位置</span>
<span class="k">if</span><span class="p">(</span><span class="k">this</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">==</span> <span class="nx">p</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span> <span class="o">||</span> <span class="nx">j</span><span class="o">==-</span><span class="mi">1</span><span class="p">){</span>
<span class="nx">i</span><span class="o">++</span><span class="p">;</span>
<span class="nx">j</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span> <span class="c1">// 查找失败,只需移动模式串的位置,不需要i回溯</span>
<span class="nx">j</span> <span class="o">=</span> <span class="nx">flink</span><span class="p">[</span><span class="nx">j</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="nx">j</span><span class="o">==</span><span class="nx">p</span><span class="p">.</span><span class="nx">length</span><span class="p">){</span> <span class="c1">//匹配成功,返回模式串在子串开始的索引下标</span>
<span class="k">return</span> <span class="nx">i</span><span class="o">-</span><span class="nx">p</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span> <span class="c1">//匹配失败,返回-1</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//KMP 算法核心(获取失败连接数组)</span>
<span class="kd">function</span> <span class="nx">getFlink</span><span class="p">(</span><span class="nx">p</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">flink</span> <span class="o">=</span> <span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">,</span><span class="mi">0</span><span class="p">];</span> <span class="c1">//为-1是为了标记第一个位置(方便之后使用flink去匹配)</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">2</span><span class="p">;</span> <span class="nx">i</span><span class="o"><</span><span class="nx">p</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">preFlink</span> <span class="o">=</span> <span class="nx">flink</span><span class="p">[</span><span class="nx">i</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>
<span class="c1">//循环寻找初始子串(从0开始的子串),这个初始子串与以 i-1 字符结尾的子串相匹配</span>
<span class="k">while</span><span class="p">(</span><span class="nx">preFlink</span> <span class="o">>-</span><span class="mi">1</span> <span class="o">&&</span> <span class="nx">p</span><span class="p">[</span><span class="nx">i</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span><span class="o">!=</span><span class="nx">p</span><span class="p">[</span><span class="nx">preFlink</span><span class="p">]){</span>
<span class="nx">preFlink</span> <span class="o">=</span> <span class="nx">flink</span><span class="p">[</span><span class="nx">preFlink</span><span class="p">];</span>
<span class="p">}</span>
<span class="nx">flink</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="nx">preFlink</span><span class="o">+</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">flink</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
前端性能优化之-force reflow
2018-06-05T20:15:00+00:00
https://blog.lisong.hn.cn/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96/2018/06/05/前端性能优化之-force reflow
<h2 id="reflow">reflow</h2>
<p>一般来说,页面的 reflow(重排)都是异步的,但是如果在 <strong>render 树已经更改的前提下</strong>,我们使用 JavaScript 获取元素的一些特殊属性或者执行了某些方法,将会使 <code class="language-plaintext highlighter-rouge">Recalculate Style</code>(样式计算)或 <code class="language-plaintext highlighter-rouge">Layout</code>(布局计算)同步执行。</p>
<p>以下是会触发同步<code class="language-plaintext highlighter-rouge">Recalculate Style</code> 和 <code class="language-plaintext highlighter-rouge">Layout</code> 的一些常见的属性和方法。</p>
<h3 id="元素">元素</h3>
<p>获取元素布局相关的属性及方法:</p>
<ul>
<li>elem.offsetLeft</li>
<li>elem.offsetTop</li>
<li>elem.offsetWidth</li>
<li>elem.offsetHeight</li>
<li>elem.offsetParent</li>
<li>elem.clientLeft</li>
<li>elem.clientTop</li>
<li>elem.clientWidth</li>
<li>elem.clientHeight</li>
<li>elem.getClientRects()</li>
<li>elem.getBoundingClientRect()</li>
</ul>
<h3 id="滚动">滚动</h3>
<ul>
<li>elem.scrollBy()/window.scrollBy()</li>
<li>elem.scrollTo()/window.scrollTo()</li>
<li>elem.scrollIntoView()</li>
<li>elem.scrollIntoViewIfNeeded()</li>
<li>elem.scrollWidth</li>
<li>elem.scrollHeight</li>
<li>elem.scrollLeft</li>
<li>elem.scrollTop</li>
</ul>
<h3 id="getcomputedstyle">getComputedStyle</h3>
<p>执行 window.getComputedStyle(dom) 方法,并且获取某个元素的布局相关属性。如果获取的属性和布局无关,则只会触发同步 <code class="language-plaintext highlighter-rouge">Recalculate Style</code> 操作;如果获取的属性和布局相关,则会触发同步<code class="language-plaintext highlighter-rouge">Recalculate Style</code> 和 <code class="language-plaintext highlighter-rouge">Layout</code>。</p>
<p>布局相关属性:</p>
<ul>
<li>height</li>
<li>width</li>
<li>top</li>
<li>right, bottom, left</li>
<li>margin [-top, -right, -bottom, -left]</li>
<li>padding [-top, -right, -bottom, -left]</li>
<li>transform</li>
<li>transform-origin</li>
<li>perspective-origin</li>
<li>translate</li>
<li>rotate</li>
<li>scale</li>
<li>perspective-origin</li>
</ul>
<p>执行 window.getComputedStyle(dom) 方法后,获取媒体查询相关属性也会触发同步 <code class="language-plaintext highlighter-rouge">Recalculate Style</code> 和 <code class="language-plaintext highlighter-rouge">Layout</code></p>
<ul>
<li>min-width</li>
<li>min-height</li>
<li>max-width</li>
<li>max-height</li>
<li>width</li>
<li>height</li>
<li>aspect-ratio</li>
<li>min-aspect-ratio</li>
<li>max-aspect-ratio</li>
<li>device-pixel-ratio</li>
<li>resolution</li>
<li>orientation</li>
<li>min-device-pixel-ratio</li>
<li>max-device-pixel-ratio</li>
</ul>
<h3 id="window">Window</h3>
<p>获取 window 对象布局相关的属性:</p>
<ul>
<li>window.scrollX</li>
<li>window.scrollY</li>
<li>window.innerHeight</li>
<li>window.innerWidth</li>
</ul>
<h2 id="测试">测试</h2>
<p>这里只对 scroll 和 getComputedStyle 进行简单的测试,其他属性方法的测试同理。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>reflow-test<span class="nt"></title></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nc">.d1</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.d2</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">110px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">110px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.outer</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">400px</span><span class="p">;</span>
<span class="nl">overflow</span><span class="p">:</span> <span class="nb">hidden</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"outer"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"d1"</span><span class="nt">></div></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"d2"</span><span class="nt">></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">div1</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.d1</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">div2</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.d2</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">function</span> <span class="nx">testScr</span><span class="p">(</span><span class="nx">flag</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nx">flag</span><span class="p">){</span>
<span class="nx">div1</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">200px</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nx">div1</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">backgroundColor</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">blue</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">scrollBy</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">testCStyle</span><span class="p">(</span><span class="nx">divNum</span><span class="p">,</span><span class="nx">prop</span><span class="p">,</span><span class="nx">ifGet</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">div</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">switch</span><span class="p">(</span><span class="nx">divNum</span><span class="p">){</span>
<span class="k">case</span> <span class="mi">1</span><span class="p">:</span> <span class="nx">div</span> <span class="o">=</span> <span class="nx">div1</span><span class="p">;</span><span class="k">break</span><span class="p">;</span>
<span class="k">case</span> <span class="mi">2</span><span class="p">:</span> <span class="nx">div</span> <span class="o">=</span> <span class="nx">div2</span><span class="p">;</span><span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">div1</span><span class="p">.</span><span class="nx">style</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">200px</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">style</span> <span class="o">=</span> <span class="nx">getComputedStyle</span><span class="p">(</span><span class="nx">div</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">ifGet</span><span class="p">){</span>
<span class="nx">style</span><span class="p">[</span><span class="nx">prop</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96/force-reflow">测试代码</a></p>
<p><br /><strong><code class="language-plaintext highlighter-rouge">testScr(true)</code> 运行结果:</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/force-reflow-1.png" alt="" /></p>
<p><br /><strong><code class="language-plaintext highlighter-rouge">testScr(false)</code> 运行结果:</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/force-reflow-2.png" alt="" /></p>
<p>由上面的两个结果可知,如果 render 树只是普通样式发生了更改,执行 scroll 相关方法后(<code class="language-plaintext highlighter-rouge">window.scrollBy(0,0)</code> 不会滚动页面),只会触发同步 <code class="language-plaintext highlighter-rouge">Recalculate Style</code>;而如果 render 树的布局发生改变,则会触发同步 <code class="language-plaintext highlighter-rouge">Recalculate Style</code> 和 <code class="language-plaintext highlighter-rouge">layout</code>。</p>
<p><br /><strong><code class="language-plaintext highlighter-rouge">testCStyle(2,'height',true)</code> 运行结果:</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/force-reflow-3.png" alt="" /></p>
<p><br /><strong><code class="language-plaintext highlighter-rouge">testCStyle(1,'backgroundColor',true)</code> 运行结果:</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/force-reflow-4.png" alt="" /></p>
<p>上面两图结果说明,用 getComputedStyle 获取元素样式对象后,如果 render 树的布局有更改,此时使用样式对象获取某个元素(div1的布局并为影响到div2)的布局相关的属性,会触发同步 <code class="language-plaintext highlighter-rouge">Recalculate Style</code> 和 <code class="language-plaintext highlighter-rouge">layout</code>;而使用样式对象获取该样式对象<strong>相关联的元素</strong>的布局无关样式属性,只会触发同步 <code class="language-plaintext highlighter-rouge">Recalculate Style</code>。</p>
<p><br /><strong><code class="language-plaintext highlighter-rouge">testCStyle(2,'backgroundColor',true)</code> 运行结果:</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/force-reflow-5.png" alt="" /></p>
<p>该结果表明用 getComputedStyle 获取元素样式对象后,此时使用样式对象获取与该样式对象<strong>无关联的元素</strong>的布局无关样式属性,即使 render 树的布局有更改,也不会触发同步 <code class="language-plaintext highlighter-rouge">Recalculate Style</code> 或者 <code class="language-plaintext highlighter-rouge">layout</code>。</p>
<p><br /><strong><code class="language-plaintext highlighter-rouge">testCStyle(1,'height',false)</code> 运行结果:</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/force-reflow-6.png" alt="" /></p>
<p>该结果表明用单独的 getComputedStyle 操作并不会触发同步操作,此时必须使用该方法返回的样式对象去真正获取某些属性时候才可能会触发同步 <code class="language-plaintext highlighter-rouge">Recalculate Style</code> 或者 <code class="language-plaintext highlighter-rouge">layout</code>。</p>
<p><br /><strong>参考:</strong></p>
<p><a href="https://gist.github.com/paulirish/5d52fb081b3570c81e3a">https://gist.github.com/paulirish/5d52fb081b3570c81e3a</a></p>
前端性能优化之-Event Loop
2018-06-04T14:06:00+00:00
https://blog.lisong.hn.cn/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96/2018/06/04/前端性能优化之-Event Loop
<h2 id="event-loop">Event Loop</h2>
<blockquote>
<p>To coordinate events, user interaction, scripts, rendering, networking, and so forth, user agents must use event loops as described in this section. There are two kinds of event loops: those for browsing contexts, and those for workers.<br /><br />
There must be at least one browsing context event loop per user agent, and at most one per unit of related similar-origin browsing contexts.<br /><br />
A browsing context event loop always has at least one browsing context.<br /><br />
A browsing context event loop always has at least one browsing context. If such an event loop’s browsing contexts all go away, then the event loop goes away as well. A browsing context always has an event loop coordinating its activities.<br /><br />
Worker event loops are simpler: each worker has one event loop, and the worker processing model manages the event loop’s lifetime<br /><br />
<em>——— <a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loops">https://html.spec.whatwg.org/multipage/webappapis.html#event-loops</a></em></p>
</blockquote>
<p>以上是 whatwg 标准定义的浏览器事件循环。在浏览器中为了协调各种任务的运行,存在着两种 EventLoop,一种是浏览器上下文事件循环,一种是 JavaScript Worker 上下文的事件循环。</p>
<p>每一个用户代理(可能有多个浏览器上下文)必须至少有一个浏览器上下文event loop,但是每个<a href="https://html.spec.whatwg.org/multipage/browsers.html#unit-of-related-similar-origin-browsing-contexts">单元的相似源浏览器上下文</a>(同源的标签页窗口)至多有一个event loop。</p>
<p>一个浏览器上下文事件循环机制至少对应着一个浏览器上下文,一个浏览器上下文总是会有一个事件循环机制。而 worker 事件循环则相对简单,一个 worker 后台线程对应一个事件循环机制。</p>
<p><a href="https://html.spec.whatwg.org/multipage/browsers.html#browsing-context">浏览器上下文</a>是一个将 Document 对象呈现给用户的环境。在一个 Web 浏览器内,一个标签页或窗口常包含一个浏览上下文,如一个 iframe 或一个 frameset 内的若干 frame。</p>
<blockquote>
<p>The rendering engine is single threaded. Almost everything, except network operations, happens in a single thread. In Firefox and Safari this is the main thread of the browser. In Chrome it’s the tab process main thread. <br /><br />
The browser main thread is an event loop. It’s an infinite loop that keeps the process alive. It waits for events (like layout and paint events) and processes them. <br /><br />
<em>——— <a href="https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/#Event_loop">https://www.html5rocks.com/en/tutorials/internals/howbrowserswork/#Event_loop</a></em></p>
</blockquote>
<p>浏览器的渲染引擎是一个单线程,网页渲染相关的操作基本上都在这个线程里完成(当然,这个单线程会会调用其他线程来协同工作),在 FireFox 和 Safari 浏览器里,这个单线程就是浏览器的主线,而在 Chrome 浏览器里,这个单线程就是渲染进程的主线程(之所以会这样,是因为 Blink 内核的多进程模型和 Webkit2 内核不一样,具体可参考<a href="https://wanls4583.github.io/2018/05/webkit学习笔记-(3)Webkit构架和模块/">Webkit构架和模块</a>)。主线程是一个事件循环,以下是 FireFox 中关于主事件循环的代码:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">while</span> <span class="p">(</span><span class="o">!</span><span class="nx">mExiting</span><span class="p">)</span>
<span class="nx">NS_ProcessNextEvent</span><span class="p">(</span><span class="nx">thread</span><span class="p">);</span>
</code></pre></div></div>
<h2 id="浏览器事件循环的运行机制">浏览器事件循环的运行机制</h2>
<p>事件循环中存在这两种任务队列:task queue(宏任务队列,网上也有人叫macrtask queue),microtask queue(微任务队列)。其实还有一个 render queue(更新队列),这个队列用来存储所有的更新操作。</p>
<blockquote>
<p>For example, a user agent could have one task queue for mouse and key events (the user interaction task source), and another for everything else. The user agent could then give keyboard and mouse events preference over other tasks three quarters of the time, keeping the interface responsive but not starving other task queues, and never processing events from any one task source out of order.<br /><br />
<em>——— <a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loops">https://html.spec.whatwg.org/multipage/webappapis.html#event-loops</a></em></p>
</blockquote>
<p>而对于宏任务队列,又可根据任务来源分为两种队列,用户交互相关的任务源的事件存储在一个队列(这个队列的优先级高,主要是为了快速响应交互),其他任务源的事件存储在另一个队列。主线程会给优先级高的队列更多的执行单元。</p>
<p>这是 whatwg 说明可能出现的情况,也就是说浏览器里可能存在两个宏任务队列(浏览器具体如何实现,要视浏览器厂商而定)。</p>
<h3 id="更新过程">更新过程</h3>
<blockquote>
<p>An event loop must continually run through the following steps for as long as it exists:</p>
<ul>
<li>Let oldestTask be the oldest task on one of the event loop’s task queues, if any, ignoring, in the case of a browsing context event loop, tasks whose associated Documents are not fully active. The user agent may pick any task queue. If there is no task to select, then jump to the microtasks step below.</li>
<li>Set the event loop’s currently running task to oldestTask.</li>
<li>Run oldestTask.</li>
<li>Set the event loop’s currently running task back to null.</li>
<li>Remove oldestTask from its task queue.</li>
<li>Microtasks: Perform a microtask checkpoint.</li>
<li>Update the rendering.If this event loop is a browsing context event loop… <br /><br />
<em>——— <a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-for-spec-authors">https://html.spec.whatwg.org/multipage/webappapis.html#event-loop-for-spec-authors</a></em></li>
</ul>
</blockquote>
<ul>
<li>首先检查宏任务队列是否为空,如果不为空,则从队列中取出最先加入的任务</li>
<li>把取出的宏任务标记为当前运行中的任务</li>
<li>执行宏任务</li>
<li>将取出的任务从宏任务队列里删除</li>
<li>执行完宏任务后,执行microtasks任务检查点</li>
<li>更新页面</li>
</ul>
<h3 id="更新详细流程">更新详细流程</h3>
<p><img src="https://wanls4583.github.io/images/posts/前端优化/2018-06-04-前端性能优化之-Event Loop-1.png" alt="" /></p>
<p>为了避免混淆,假设是从最近的一次页面更新完成后开始执行主循环的。</p>
<ol>
<li>首先,检查宏任务队列是否有任务,如果不为空,则取出最早加入队列的一个任务(宏任务里的任务都是按添加的时间点,按序执行的),并且主线程将切换到 JavaScript 线程执行任务。此时,主线程将停止事件循环,直到 JavaScript 线程执行完成所有同步代码,执行完成后,跳至步骤2。在这个过程中,可能会产生新的宏任务和微任务,它们会分别被加到相应的队列里,等待主线程取出它们去执行。如果在执行任务的期间使用 JavaScript 更改了样式或者DOM元素,使页面需要 reflow/repaint,则浏览器会将这些更改添加到更新队列。如果宏任务队列为空,则跳至步骤2。<br /><br /></li>
<li>检查微任务队列是否为空,如果不为空,则取出最早加入队列的一个任务执行(任务的执行顺序同宏任务队列),其后的执行和步骤 1 一致,只不这里会循环的执行完队列里所有的微任务,执行期间产生的微任务会加入到微任务队列,并且会在本次主循环中都执行完。<br /><br /></li>
<li>检查页面是否需要更新,这里检查机制并不是简单的检查更新队列是否为空,浏览器还会考虑到屏幕刷新频率等因素(以下的引用有说明),标准中没有定义具体的规则。比如说,以大于 60HZ 的频率更新页面是没有必要的,因为 30HZ-60HZ 的更新频率在肉眼看来已经很流畅了。如果确定需要更新,则主线程切换到渲染线程,此时,主线程将停止事件循环,直到页面渲染完成。
在执行具体的更新操作操作之前,浏览器会依次触发下面的事件:<br /><br />
<ul>
<li>dispatch pending UI events</li>
<li>resize event</li>
<li>scroll event</li>
<li>mediaquery listeners</li>
<li>CSSAnimation events</li>
<li>Observers</li>
<li>rAF</li>
</ul>
</li>
</ol>
<blockquote>
<p>There are two classes of UI events:</p>
<ul>
<li>Discrete - those that aren’t continuous (eg. mousedown, mouseup, touchstart, touchend).</li>
<li>Continuous - mousewheel, wheel, mousemove, pointermove, touchmove.<br /><br />
<em>——— <a href="https://github.com/atotic/event-loop">https://github.com/atotic/event-loop</a></em></li>
</ul>
</blockquote>
<p>如果页面有注册这些事件的函数,则会生成一个宏任务放进宏任务队里,并返回事件循环。当由这一步触发的事件任务经过事件循环都执行完成后,最后才是真正的更新操作。如果在执行任务的期间使用 JavaScript 更改了样式或者DOM元素,使页面需要 reflow/repaint,则浏览器会将这些更改添加到更新队列,并在本轮更新中更新。</p>
<p>这些事件是依次触发的,Chrome正常,不过有些浏览器会与标准不一致<a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/前端优化/event-loop/dispatch-order">(测试)</a>。</p>
<h4 id="更新流程验证">更新流程验证</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nt">body</span><span class="o">,</span><span class="nt">html</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.d1</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.d2</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"d1"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"d2"</span><span class="nt">></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">testST</span><span class="p">(){</span>
<span class="nx">requestAnimationFrame</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.d1</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">200px</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">RAF</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">scroll</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.d1</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">400px</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.d1</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">backgroundColor</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">green</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">timeout</span><span class="dl">'</span><span class="p">);</span>
<span class="p">},</span><span class="mi">0</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">scroll</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">sleep</span><span class="p">(</span><span class="mi">200</span><span class="p">);</span>
<span class="p">});</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">scrollBy</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">10</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">testPro</span><span class="p">(){</span>
<span class="nx">requestAnimationFrame</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.d1</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">200px</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">RAF</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">scroll</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.d1</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">width</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">400px</span><span class="dl">'</span><span class="p">;</span>
<span class="nb">Promise</span><span class="p">.</span><span class="nx">resolve</span><span class="p">().</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.d1</span><span class="dl">'</span><span class="p">).</span><span class="nx">style</span><span class="p">.</span><span class="nx">backgroundColor</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">green</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">promise</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">scroll</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">sleep</span><span class="p">(</span><span class="mi">200</span><span class="p">);</span>
<span class="p">});</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">scrollBy</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">10</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">sleep</span><span class="p">(</span><span class="nx">t</span><span class="p">){</span>
<span class="kd">let</span> <span class="nx">start</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="k">while</span><span class="p">(</span><span class="kc">true</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span> <span class="o">-</span> <span class="nx">start</span> <span class="o">>=</span> <span class="nx">t</span><span class="p">){</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>操作:</p>
<ul>
<li>打开页面后,切换到调试工具 Performance 选项卡,点击 record 按钮开始记录页面事件活动</li>
<li>在控制台输入 testST() 运行函数</li>
</ul>
<p><strong><code class="language-plaintext highlighter-rouge">testST()</code> 结果:</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/event-loop-1.png" alt="" /></p>
<p>从结果中可以看到,同时执行 requesAnimationFrame 和 scroll,在更新时会先触发 scroll 事件,然后再触发 animationFrame 事件。由于在 scroll 回调里暂停了 200ms,这两个任务执行完成之前,队列里还有一个 timer 任务待执行,但是,主线程在执行完由 render 过程触发的任务后会立即开始执行更新操作,所以 timer 任务里的样式更改,需要在下一个 render 过程才会被页面跟新。</p>
<p>如果运行 testPro(),结果则不是这样了。这里将 setTimout 换成了 promise, 由于 requesAnimationFrame 和 scroll 也是宏任务,所以在执行完回调后,会检查微任务队列并执行所有任务,所以里面的样式更改会在本次 render 过程里被更新到页面。</p>
<p><strong><code class="language-plaintext highlighter-rouge">testPro()</code> 结果:</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/event-loop-2.png" alt="" /></p>
<h3 id="垂直同期vsync">垂直同期(vSync)</h3>
<blockquote>
<p>Whether a top-level browsing context would benefit from having its rendering updated depends on various factors, such as the update frequency. For example, if the browser is attempting to achieve a 60Hz refresh rate, then these steps are only necessary every 60th of a second (about 16.7ms). If the browser finds that a top-level browsing context is not able to sustain this rate, it might drop to a more sustainable 30Hz for that set of Documents, rather than occasionally dropping frames. (This specification does not mandate any particular model for when to update the rendering.) Similarly, if a top-level browsing context is in the background, the user agent might decide to drop that page to a much slower 4Hz, or even less.<br /><br />
<em>——— <a href="https://html.spec.whatwg.org/multipage/webappapis.html#event-loop">https://html.spec.whatwg.org/multipage/webappapis.html#event-loop</a></em></p>
</blockquote>
<blockquote>
<p>Render part of the loop gets executed on vSync<br /><br />
<em>——— <a href="https://github.com/atotic/event-loop">https://github.com/atotic/event-loop</a></em></p>
</blockquote>
<p>浏览器在执行完微任务后检查是否有必要更新页面,它会以垂直同期的方式更新页面,这里的垂直同期指的是,浏览器可能会根据屏幕的刷新频率来更新页面,多数时候,屏幕的更新频率是 60HZ(一秒钟60次),也即浏览器只要以约 16.7ms 的间隔更新页面就可以实现流畅的画面,在 16.7ms 内的更新检查将会返回 false。</p>
前端性能优化之-Chrome timing详解
2018-06-01T14:26:00+00:00
https://blog.lisong.hn.cn/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96/2018/06/01/前端性能优化之-Chrome timing详解
<p><img src="http://wanls4583.github.io/images/posts/前端优化/chrome-timing-1.png" alt="" /></p>
<ul>
<li><strong>Queued at:</strong> 请求加入到队列中的时间点(相对于 HTML 文档下载完成的时间)。</li>
<li><strong>Started at:</strong> 从队列里取出请求,并开始发送请求的时间点(相对于 HTML 文档下载完成的时间)。</li>
<li><strong>Queueing:</strong> 请求在队列里排队所花费的时间。相比关键资源(JavaScript、CSS),图片等资源的优先级比较低,通常会被浏览器放在队列中延迟请求。</li>
<li><strong>Stalled:</strong> 请求被阻塞的时间。有多种情况会使请求被阻塞,典型的有如下两种:
<ol>
<li>TCP 连接验证。TCP三次握手后,浏览器发送数据后,一段时间内(不同的操作系统时间段不同)接收不到服务端ACK包,就会以 某一时间间隔(时间间隔一般为指数型增长)重新发送,从重传开始到接收端正确响应的时间就是stalled阶段。</li>
<li>在 HTTP 1 中,浏览器仅允许每个源最多同时拥有六个 TCP 连接,当超过6个后,后面的请求将被阻塞。</li>
</ol>
</li>
<li><strong>DNS Lookup:</strong> DNS 解析所花费的时间。</li>
<li><strong>Initial connection:</strong> 三次握手所花费的时间。(如果是 HTTPS 协议,这里面的时间花费还包括一个 SSL 安全验证的时间)。</li>
<li><strong>Request sent:</strong> 请求第一个字节发出前到最后一个字节发出后的时间,也就是上传时间。</li>
<li><strong>Waiting(TTFB):</strong> 网络请求被发起(Request sent 之后)到从服务器接收到第一个字节这段时间。</li>
<li><strong>Content Download:</strong> 资源下载时间。</li>
</ul>
<h2 id="实践">实践</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test1.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test2.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test3.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test4.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test5.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test6.css"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>this is a test<span class="nt"></h1></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"1.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"2.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"3.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"4.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"5.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"6.png"</span><span class="nt">></span>
<span class="nt"><hr></span>
<span class="nt"><span></span>this is a test<span class="nt"></span></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"test.js"</span><span class="nt">></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><a href="https://github.com/wanls4583/wanls4583.github.io/tree/master/code/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96/chrome-timing">示例代码</a></p>
<p>为了方便测试,以下所有的测试都是在 Fast 3G 网络模拟下进行的。</p>
<p><strong>结果</strong>(Chrome(版本 63.0.3239.84(正式版本) (32 位)))</p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/chrome-timing-2.png" alt="" /></p>
<p>图中的色条所代表的时段对应为:</p>
<ul>
<li>绿色->Waiting(TTFB)</li>
<li>褐色->Stalled</li>
<li>白色->Queueing</li>
<li>蓝色->Content Download</li>
</ul>
<p>从图中可以分析出如下结论:</p>
<ul>
<li>对于同等优先级的资源,当并行下载超过6个以后,后面的请求将被阻塞(Stalled),图中的 test.js、7.png 资源就是这种情况。</li>
<li>对于低优先级的资源(图片),如果当前有一个高优先级的资源(JavaScript、CSS)请求还没有完成,则最多允许一个(不同浏览器或者相同浏览器的不同版本允许的规则可能不一样,例如版本为 63.0.3239.84 的 Chrome 浏览器是一个,而版本为 67.0.3396.62 的 Chrome 浏览器是两个)低优先级的资源和高优先级的资源并行加载。图中只有 1.png 和 test.js 并行下载,其他图片此时都在队列里派对(Queueing)。</li>
</ul>
<p><strong>结果</strong>(Chrome(版本 67.0.3396.62(正式版本) (32 位)))</p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/chrome-timing-3.png" alt="" /></p>
<p>版本为 67.0.3396.62 的 Chrome 浏览器最多允许两个低优先级的资源和高优先级的资源并行加载。</p>
<p>此时,如果将 JavaScript 资源放到最后</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test1.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test2.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test3.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test4.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test5.css"</span><span class="nt">></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test6.css"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>this is a test<span class="nt"></h1></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"1.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"2.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"3.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"4.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"5.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"6.png"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"7.png"</span><span class="nt">></span>
<span class="nt"><hr></span>
<span class="nt"><span></span>this is a test<span class="nt"></span></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"test.js"</span><span class="nt">></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>结果</strong>(Chrome(版本 63.0.3239.84(正式版本) (32 位)))</p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/chrome-timing-4.png" alt="" /></p>
<p><strong>结果</strong>(Chrome(版本 63.0.3239.84(正式版本) (32 位)))</p>
<p><img src="http://wanls4583.github.io/images/posts/前端优化/chrome-timing-5.png" alt="" /></p>
<p>可以看到,如果将 JavaScript(高优先级)资源放到最后,则最多允许5个图片(低优先级)资源同 JavaScript(高优先级)资源一起并行加载。</p>
webkit学习笔记-(6)CSS解释器和样式布局
2018-06-01T00:00:00+00:00
https://blog.lisong.hn.cn/webkit/2018/06/01/webkit学习笔记-(6)CSS解释器和样式布局
<h2 id="css-基本功能">CSS 基本功能</h2>
<h3 id="框模型">框模型</h3>
<p><img src="http://wanls4583.github.io/images/posts/webkit/CSS解释器-1.png" alt="" /></p>
<p>框模型是布局计算的基础,渲染引擎可以根据框模型来理解该如何排版元素以及元素之间的位置关系。</p>
<h3 id="包含块模型">包含块模型</h3>
<p>当WebKit计算元素的箱子的位置和大小时,WebKit需要计算该元素和另外一个矩形区域的相对位置,这个矩形区域成为该元素的包含块。框模型就是用在包含块内计算和确定各个元素的。</p>
<p>包含块的具体定义如下:</p>
<ul>
<li>根元素的包含块称为初始包含块,通常它的大小就是可视区域(Viewport)的大小。</li>
<li>对于其他位置属性设置为static或者relative的元素,它的包含块就是最近祖先的箱子模型中内容区域(Content)。</li>
<li>如果元素的位置属性为fixed,难么该元素的包含块脱离HTML文档,固定在可视区域的某个特定位置。</li>
<li>如果元素的位置属性为absolute,那么该元素的包含块由最近的含有属性absolute,relative,fixed的祖先决定。</li>
</ul>
<h3 id="cssomcss-object-model">CSSOM(CSS Object Model)</h3>
<p>CSSOM 定义了样式表的接口,称为“CSSStyleSheet”,JavaScript 可以通过该接口动态操作 CSS 样式。例如可以通过 document.stylesheets 查看当前网页中包含的所有 CSS 样式表。</p>
<p>此外,W3C 还定义了另外一个规范,那就是 CSSOM View,它的基本含义是增加一些新的属性到 Window、Document、Element、HTMLElement 和 MouseEvent 等接口,这些 CSS 的属性能够让 JavaScript 获取视图信息,用于表示跟视图相关的特征,例如窗口大小、网页滚蛋位置、元素的框位置、鼠标事件的坐标等信息。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/CSS解释器-2.png" alt="" /></p>
<h2 id="css-解释器和规则匹配">CSS 解释器和规则匹配</h2>
<p>CSS 的内部结构主要类和关系:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/CSS解释器-3.png" alt="" /></p>
<p>DocumentStyleSheetCollection 类包含了所有 CSS 样式表,CSSStyleSheet 包含了 CSS 的 href、类型、内容等信息。CSS 的内容就是样式信息 StyleSheetContents,包含了一个样式规则(StyleRuleBase)列表。</p>
<p>StyleSheetResolver 类将解释之后的规则组织起来,用于为 DOM 中的元素匹配相应的而规则,从而应用规则中的属性值序列。它包含了一个 DocumentRuleSets 类,该类用来表示多个规则集合(RuleSet)。每个规则集合都是将之前解释之后的的结果合并起来,并进行分类,例如 id 类规则、标签类规则等。由于规则可能是用户自定义的,也有可能是浏览器默认的,所以会有多个规则集合。</p>
<p>StyleRuleBase 有一个子类 StyleRule,其内部结构如下:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/CSS解释器-4.png" alt="" /></p>
<p>CSS 解释器的工作如下:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/CSS解释器-5.png" alt="" /></p>
<p>样式规则建立完成之后,Webkit 保存规则结果在 DocumentRuleSets 对象类中。当 DOM 的节点建立之后,Webkit 使用 StyleResolver 类根据元素的信息(标签名、类别等),从样式表中查找匹配的规则,然后将样式信息保存到新建的 RenderStyle 对象中。最后,这些 RnederStyle 对象被 RenderObject 类所管理和使用。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/CSS解释器-6.png" alt="" /></p>
<p>当使用 JavaScript 动态设置样式属性值时,JavaScript 引擎会调用设置属性值的公共处理函数,然后该函数调用属性值解析函数。而后 Webkit 将解析后的信息设置到元素的“style”属性中,然后设置标记表明该元素需要重新计算样式,并触发重新计算布局。</p>
<h2 id="webkit-布局">Webkit 布局</h2>
<p>当 Webkit 创建 RenderObject 对象之后,每个对象是不知道自己的位置、大小等信息的,Webkit 根据框模型来计算它们的位置、大小等信息的过程称为布局计算(或者称为排版)。</p>
<p>布局计算根据其计算的范围大致可以分为两类:第一个类是对整个 RnederObject 树进行的计算;第二类是对 RenderObject 树中的某个子树的计算,常见于文本元素或者是 overflow:auto 快的计算,这种情况一般是其子树布局的改变不会影响到其周围元素的布局。</p>
<p>布局计算是一个递归的过程,一个节点的大小通常需要先计算它的子节点的位置、大小信息。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/CSS解释器-7.png" alt="" /></p>
<p>布局计算主要的主要逻辑都是由 RenderObject 类的“layout”函数来完成。该函数首先需要判断 RenderObject 是否需要重新计算,通常这需要检查位数组中的相应标记位、子女是否需要计算布局等来确定。然后,该函数会确定网页的宽度和垂直方向上的外边距,最后,该函数会遍历其每一个子女节点,依次计算它们的布局,每个子女节点都有自己的“layout”函数。</p>
<p>除非定义了页面元素的宽高,一般来说页面的元素的宽高都是在布局的时候通过相关计算得出来的。如果元素有它的子女,则 Webkit 递归这一过程。</p>
<p>以下情况都有可能使 Webkti 重新计算布局:</p>
<ul>
<li>首次打开网页</li>
<li>网页中的动画</li>
<li>通过 JavaScript 改变元素的样式</li>
<li>用户的交互,例如翻滚网页</li>
</ul>
webkit学习笔记-(5)HTML解释器和DOM模型
2018-05-31T00:00:00+00:00
https://blog.lisong.hn.cn/webkit/2018/05/31/webkit学习笔记-(5)HTML解释器和DOM模型
<h2 id="dom-模型">DOM 模型</h2>
<p>DOM(Document Object Model)定义的是一组与平台、语言无关的接口,该接口允许编程语言动态访问和更改结构化文档。W3C标准化组织定义一系列 DOM 接口,随着时间的推移,目前已经形成了三个演进的标准:DOM Level 1、DOM Level 2、DOM Level 3,每个 Level 都是在原有的基础上增加新的接口以加强功能。各个阶段比较重要的功能如下:</p>
<ul>
<li>Level 1
<ul>
<li>Core: 支持 XML 文档</li>
<li>HTML: 在 Core 的基础上对 HTML 文档进行访问,把 HTML 中的内容定义为文档(Document)、节点(Node)、属性(Attribute)、元素(Element)、文本(Text)等。</li>
</ul>
</li>
<li>Level 2
<ul>
<li>Core: 扩展 Level 1 Core,如新增 getElemntById</li>
<li>Events: 引入了对 DOM 事件的处理,支持 EventTarget、Mouse 事件等接口,但仍然不支持键盘事件,这个事件在 DOM Level 3才被加入</li>
<li>HTML: 扩充 Level 1 HTML,允许动态访问和修改 HTML 文档</li>
</ul>
</li>
<li>Level 3
<ul>
<li>Core: 新增 adoptNode 和 textContent</li>
<li>Events: 主要加入了对键盘的支持</li>
</ul>
</li>
</ul>
<p>由于 DOM 的定义是与语言无关的,所以标准中所有这些都是接口,它支持不同类型的语言,例如 C++、Java 或者 Javascript。</p>
<h2 id="html-解释器">HTML 解释器</h2>
<h3 id="解释过程">解释过程</h3>
<p><img src="http://wanls4583.github.io/images/posts/webkit/HTML解释器-1.png" alt="" /></p>
<p>在 Webkit 中,首先对字节流解码获得字符流,如果 HTML 网页中设置了编码格式,则 Webkit 会使用相应的解码器来将字节流转换成特定格式的字符串。然后通过词法解析器解释成词语(Tokens),之后经过语法分析器构建成节点,最后这些节点被组建成一棵 DOM 树。</p>
<h3 id="节点到-dom-树">节点到 DOM 树</h3>
<p>Webkit 在解析 HTML 文档时使用了栈结构,例如一个片段“<code class="language-plaintext highlighter-rouge"><body><div><img></img></div></body></code>”,当解释到 img 元素的开始标记时,栈中的元素就是 body、div、img,当遇到 img 的结束标记时,img 退栈,img 是 div 的子女;当遇到 div 的结束标记时,div 退栈,表明 div 和它的子女都已经处理完,依次类推。</p>
<p>同 DOM 标准一样,一切的基类都是 Node 类。在 Webkit 中,DOM 中的接口 Interface 对应于 <em>C++ 类</em>,Node 类是其他类的基类。</p>
<p>Webkit 中节点相关的类如下:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/HTML解释器-2.png" alt="" /></p>
<h3 id="网页基础设施">网页基础设施</h3>
<p>Webkit 中的基础设施类时被各个移植所共享的,移植通过调用这些类来进行布局、渲染等操作,下图描述了 Chrominum 是如何调用 Webkit 接口的。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/HTML解释器-3.png" alt="" /></p>
<p>图中左边是 Webkit 的 Chrominum 移植实现使用的接口类,WebView 和 WebFrame 类分别表示网页和网页框,WebViewImpl 和 WebFrameImpl 是 Chrominum 实现的子类,它们负责使用 Page、Frame 等 WebCore 中的类来支持两个对外类的接口。Page类是 Webkit 内部用来表示网页的类,WebView 是 Webkit 对外表示网页的类,Frame 类和 WebFrame 类也是这样的关系。</p>
<p>这里的 Chrome 是 Webkit 的一个类,表示的是网页所绘制的与实现相关的一个窗口。其具备获取各个平台资源的能力,例如 Webkit 可以调用 Chrome 类来创建一个新窗口(可以是 JavaScript 的 alert 窗口)。</p>
<h3 id="线程化的解释器">线程化的解释器</h3>
<p>在 Webkit 中,网络资源的字节流自 IO 线程传递给渲染线程之后,后面的解释、布局、和渲染工作基本上都是在该线程,也就是渲染线程完成的。因为 DOM 树只能在渲染线程上创建和访问,也就是说构建 DOM 树的过程只能在渲染线程中进行。但是,从字符串到词语这个阶段可以交给单独的线程来做。在Webkit 的 Chrominum 移植中就是将这一过程放在在单独的线程中,在该线程中将字符串解释成词语之后,Webkit 会分批次地将结果传递给渲染线程。</p>
<h3 id="javascript-的执行">JavaScript 的执行</h3>
<p>因为 JavaScript 的执行可能会调用例如“document.write()”来修改文档结构,所以 JavaScript 代码的执行会阻碍后面节点的创建,同时也会阻碍后面的资源的下载,为了解决这个问题,Webkit 使用预扫描和预加载机制来实现资源的并发下载而不被 JavaScript 的执行而阻碍。</p>
<p>具体的做法是,当遇到需要执行 JavaScript 的时候,Webkit 先暂停当前 JavaScript 代码的执行,使用预先扫描器 HTMLpreLoadScanner 类来扫描后面的词语。如果 Webkit 发现它们需要使用其他资源,那么使用预资源加载器 HTMLResourcePreloader 类来发送请求,在这之后,才执行 JavaScript 的代码。预先扫描器本身并不创建节点对象,也不会构建 DOM 树,所以速度比较快。不过,并不是所有渲染引擎都像 Webkit 这样处理,所以开发网页时尽量把 script 标签放到最后。</p>
<h2 id="dom-的事件机制">DOM 的事件机制</h2>
<h3 id="事件的工作过程">事件的工作过程</h3>
<p>事件在工作过程中使用两个主体,第一个是事件(Event),第二个是事件目标(EventTarget)。当渲染引擎接收到一个事件的时候,它会通过 HitTest(Webkit 中的一种检查触发事件在哪个区域的算法)检查哪个元素是直接的事件目标。然后,事件会经过捕获和冒泡两个过程。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/HTML解释器-4.png" alt="" /></p>
<p>捕获过程是自顶向下的,中间的元素可以捕获该事件,通过事件的“stopPropagation”函数可以阻止事件的向下传递。事件的冒泡过程是从下向上的,在冒泡的过程中,中间的元素也可以响应该事件,同样,通过事件的“stopPropagation”函数可以阻止事件的向上传递。</p>
<h3 id="webkit-的事件处理机制">Webkit 的事件处理机制</h3>
<p>基于 Webkit 的浏览器事件处理过程,首先是做 HitTest,查找事件发生的元素,检测该元素有无监听者。如果发现有监听者,它需要将这些事件传递给 Webkit,Webkit 实际上最后调用 JavaScript 引擎来触发监听者函数。</p>
<h2 id="影子-dom">影子 DOM</h2>
<p>影子 DOM 的规范草案能够使得一些 DOM 节点在特定范围内可见,而在网页的 DOM 树中却不可见,但是网页渲染的结果中包含了这些节点,这就使得封装变得容易很多。通常的接口是不能直接访问到影子 DOM 子树中的节点的,JavaScript 代码只能通过特殊的接口方式。其实,video 等有控制界面的元素就是使用了影子 DOM 的思想。</p>
<p>对于影子 DOM 子树,事件目标其实就是包含影子 DOM 子树的节点对象。事件捕获的逻辑没有发生变化,在影子 DOM 子树内也会继续传递。当影子 DOM 子树中的事件向上冒泡的时候,Webkit 会同时向整个文档的 DOM 上传递该事件,以避免一些奇怪的行为。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/HTML解释器-5.png" alt="" /></p>
<h3 id="使用影子-dom">使用影子 DOM</h3>
<p><img src="http://wanls4583.github.io/images/posts/webkit/HTML解释器-6.png" alt="" /></p>
webkit学习笔记-(4)资源加载和网络栈
2018-05-28T00:00:00+00:00
https://blog.lisong.hn.cn/webkit/2018/05/28/webkit学习笔记-(4)资源加载和网络栈
<h2 id="webkit-资源加载机制">Webkit 资源加载机制</h2>
<h3 id="资源">资源</h3>
<p>HTML 支持的资源主要包括以下类型:</p>
<ul>
<li>HTML文档</li>
<li>JavaScript 文件</li>
<li>CSS 样式文件</li>
<li>图片</li>
<li>SVG</li>
<li>CSS Shader</li>
<li>视频、音频和字幕:多媒体资源及支持音视频的字幕文件(TextTrack)</li>
<li>字体文件</li>
<li>XSL 样式表:使用 XSLT 语言编写的 XSLT 代码文件</li>
</ul>
<p>上面这些资源在 Webkit 中均有不同的类来表示它们,它们的公共基类是 CachedResource。HTML 对应的资源类型叫 CachedRawResource 类。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-1.png" alt="" /></p>
<p>资源类的前面一般以“Cached”开头,所有资源在请求之前都会先获取缓存中的信息,以决定是否向服务器提出资源请求。</p>
<h3 id="资源缓存">资源缓存</h3>
<p>当 Webkit 需要请求资源的时候,先从资源池中查找是否存在相应的资源。如果有,Webkit 则取出以便使用;如过没有,Webkit 创建一个新的 CachedResource 子类的对象,并发送真正的请求给服务器,Webkit 收到资源后将其设置到该资源类的对象中去,以便于缓存后下次使用。这里的缓存指的时是内存缓存,而不同于后面在网络栈部分的磁盘缓存。</p>
<p>Webkit 从资源池中查找资源的关键字是 URL,所以即使两个资源内存完全一样,但只要 URL 不同,也被认为是两个不同的资源。</p>
<h3 id="资源加载器">资源加载器</h3>
<p>Webkit 总共三种类型的资源加载器:</p>
<ul>
<li>针对每种资源类型的特定加载器:Fontloader、ImageLoader等;</li>
<li>缓存机制的资源加载器:CachedResourceLoader,所有特定加载器都会先通过缓存机制的资源加载器来查找是否有缓存资源;</li>
<li>通用资源加载器:ResourceLoader,</li>
</ul>
<h3 id="加载过程">加载过程</h3>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-2.png" alt="" /></p>
<p>资源的加载通常是异步执行的,也就是资源的加载不会阻碍当前 Webkit 的渲染过程,例如图片、CSS 文件。当然,也有些资源会阻碍主线程的渲染过程,例如 JavaScript 代码文件。当遇到这中情况时,Webkit 会启动另外一个线程去遍历后面的 HTML 网页,收集需要的资源 URL,然后发送请求,这样就可以避免被阻碍。与此同时,Webkit 能够并发下载这些资源,甚至并发下载 JavaScript 代码资源。</p>
<h3 id="资源的生命周期">资源的生命周期</h3>
<p>内存中资源池是有限的,Webkit 采用 LRU(Least Recent Used 最近最少使用)算法来替换其中的旧资源,加入新的资源。</p>
<h3 id="资源缓存实践">资源缓存实践</h3>
<p>默认情况下,浏览器是会启动资源缓存的,当我们使用调试工具开启 Disable cache 后,则浏览器在请求资源时会加上 “Pragma: no-cache” 字段,加载机制检查到该字段后会直接发起网络请求,而不会再检查缓存池,并且会将请求中的 If-Modified-since、If-None-Match 等和缓存生命周期相关的字段去掉。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-3.png" alt="" /></p>
<h2 id="chrominum-多进程资源加载">Chrominum 多进程资源加载</h2>
<p>在 Chrominum 中,获取资源的方式是利用多进程的资源加载架构。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-4.png" alt="" /></p>
<p>在 ResourceHandle 类之下的部分,是不同移植对获取资源的不同实现。Render 进程的资源获取世纪上是通过进程间通信将任务交给 Browser 进程来完成,Browser 进程有权限从<strong>网络或者本地</strong>获取资源。从网络或者本地文件读取信息的是 URLRequest 类,它承担了建立网络连接、发送请求数据和接收回复数据的任务。</p>
<p>因为每个 Render 进程某段时间内可能有多个请求,同时还有多个 Render 进程,Browser 进程需要处理大量的资源请求,这就需要一个处理这些请求的调度器,这就是 Chrominum 中的 ResourceScheduler。ResourceScheduler 类管理的对象就是上图中的 URLRequest 对象。ResourceScheduler 类根据 URLRequest 的标记和优先级来调度 URLRequest 对象,每个 URLRequest 对象都有一个 ChildId 和 RouteId 来标记属于哪个 Render 进程。ResourceScheduler 类中有一个哈希表,该表按照进程来组织 URLRequest 对象。对于以下类型的网络请求,将立即被 Chrominum 发出:</p>
<ul>
<li>高优先级的请求</li>
<li>同步请求</li>
<li>具有 SPDY 能力的服务器</li>
</ul>
<h2 id="网络栈">网络栈</h2>
<h3 id="webkit-网络设施">Webkit 网络设施</h3>
<p>Webkit 从网络加载资源其实是由各个移植来实现的,所以 WebCore 其实并没有什么特别的基础设施,每个移植的网络实现是非常不一样的。</p>
<h3 id="chrominum-网络栈">Chrominum 网络栈</h3>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-5.png" alt="" /></p>
<h4 id="结构">结构</h4>
<p>Webkit 使用 HttpTransactionFactory 对象创建一个 HttpTransaction 对象来表示开启一个 HTTP 连接的事务。通常情况下,HttpTransaction 对象对应的是一个它的子类 HttpCache 对象。HttpCache 类使用<strong>本地磁盘缓存机制</strong>,如果该请求对应的回复已经在磁盘缓存中,那么 Chrominum 无需再建立 HttpTransaction 来发起连接,而是直接从磁盘中获取即可。如果磁盘缓存中没有该 URL 的缓存,同时如果该 URL 请求对应的 HttpTransaction 已经建立,那么只要等待它的回复即可。当这些条件都不满足的时候,Chrominum 才会真正创建 HttpTransaction 对象。</p>
<p>本地磁盘缓存中的文件在磁盘空间足够的情况下是有生命周期的,生命周期主要依据 Http 请求返回的字段来设置,具体可参考 <a href="http://lisong.online/2018/02/HTTP缓存/">http 缓存</a></p>
<h4 id="域名解析">域名解析</h4>
<p>Chrominum 中使用 HostResolverImpl 类来解析域名。为了考虑效率,使用 HostCache 类来保存解析后的域名,最多时会有多达1000个的域名和地址映射关系会被存储起来。可以在 Chrome 浏览器地址栏中输入“chrome://net-internals/#dns”来查看。</p>
<h3 id="磁盘本地缓存">磁盘本地缓存</h3>
<h4 id="特性">特性</h4>
<ul>
<li>磁盘空间有限,需要有相应的机制来移除合适的缓存资源,以便加入新的资源</li>
<li>能确保在浏览器崩溃时不破坏磁盘文件</li>
<li>支持同步和异步两种方式访问磁盘</li>
<li>磁盘不支持多线程访问,需要把所有的磁盘缓存操作放入单独一个线程</li>
</ul>
<h4 id="结构-1">结构</h4>
<p>Webkit 磁盘缓存机制对外接口主要有两个类:Backend 和 Entry。Backend 类表示整个磁盘缓存,是所有针对磁盘缓存操作的主入口,表示的是一个缓存表。Entry 类指的是表中的项。每个项由关键字来唯一确定,这个关键字就是资源的 URL。可以通过“chrome://view-http-cache/”来查看这些项。</p>
<p>Chrominum 至少需要一个索引文件和四个数据文件(数据文件名形如“data_x”)。当资源文件大小超过一定值的时候,Chrominum 会建立单独的文件来保存他们(文件名形如“f_xxxxx”),而不是将它们放入上面的4个数据文件中。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-6.png" alt="" /></p>
<p>如果手动删除cache文件夹,chrome 浏览器启动时会重新创建 cache 文件夹,并生成四个 data_x 文件和一个 index索引文件。</p>
<h3 id="cookie-机制">Cookie 机制</h3>
<p>一个网页的 Cookie 只能被该网页(或者说是该域的网页)访问。根据 Cookie 的时效性可以将 Cookie 分成两种类型,第一种是会话型 Cookie(Session Cookie),这些 Cookie 只是保存在内存中,当浏览器退出的时候即清除这些 Cookie。如果 Cookie 没有设置失效时间,就是会话型 Cookie。第二中是持续型 Cookie(Persistent Cookie),也就是当浏览器退出的时候,仍然保留 Cookie 的内容。该类型的 Cookie 有一个有效期,在有效期内,每次访问该 Cookie 所属域的时候,都需要将该 Cookie 发送个服务器,这样服务器就能够追踪用户的行为。</p>
<h3 id="高性能网络栈">高性能网络栈</h3>
<h4 id="dns-预取和-tcp-预连接preconnect">DNS 预取和 TCP 预连接(Preconnect)</h4>
<p>依次 DNS 查询的平均时间大概是 60-120ms,而 TCP 的三次握手时间大概也是几十毫秒。为了有效的减少这段时间,Chrominum 使用 “Predictor”机制来实现 DNS 预取和 TCP 预连接。</p>
<p>DNS 预取技术主要思想是利用现有的 DNS 机制,提前解析网页中可能的网络连接。具体来讲,当用户正在浏览当前网页的时候,Chrominum 提取网页中的超链接,将域名提取出来,利用比较少的 CPU 和网络带宽来解析这些域名或 IP 地址,这样一来,用户根本感觉不到这一过程。</p>
<p>DNS 预取技术不是使用前面提到的 Chrominum 网络栈,而是直接利用系统的域名解析机制,所以它不会阻碍当前网络栈的工作。而且 DNS 预取技术针对多个域名采取并行处理的方式,每个域名的解析须由新开启的一个线程来处理,结束后此线程即退出。</p>
<p>在HTML文档中,可以显示指定预取哪些域名,具体做法是添加特殊的link标签:<code class="language-plaintext highlighter-rouge"><link rel="dns-prefetch" href="https://www.baidu.com"></code>。另外,当用户在地址中输入地址后,在用户敲击回去建之前,Chrominum 已经开始使用 DNS 预取技术解析该域名了。可以通过“chrome://dns/”查看 Chrominum 的 DNS 预取的域名。</p>
<p>Chrominum 使用追踪技术来预测用户接下来将点击什么超链接,当有足够的把把握时,就可以预先建立 TCP 连接。同 DNS 预取技术一样,追踪技术不仅应用于网页中的超链接,当用户在地址栏中输入地址,在用户敲下回车键之前,Chrominum 可能就已经开始尝试建立 TCP 连接了。</p>
<h4 id="http-管线化pipelining">HTTP 管线化(Pipelining)</h4>
<p>HTTP1.1 开始增加了管线化技术。Chrominum 当然也支持这一技术,但它需要服务器的支持,两者配合才能实现 HTTP 管线化。</p>
<p>HTTP 管线化技术允许多个 http 请求通过一个套接字同时被输出 ,而不用等待相应的响应。然后请求者就会等待各自的响应,这些响应是按照之前请求的顺序依次到达。(所有请求保持一个<strong>FIFO</strong>的队列,同时,服务器端返回这些请求的响应时也是按照<strong>FIFO</strong>的顺序)</p>
<p>管线化技术需要通过<strong>持久连接</strong>来完成,并且<strong>只有 GET 和 HEAD 等请求</strong>可以进行管线化,使用场景有很大的限制。</p>
<h3 id="spdy">SPDY</h3>
<p>SPDY 是一种新的会话层协议,在 HTTP2.0 的草案中被引入,被定义在 HTTP 协议和 TCP 协议之间。</p>
<p>SPDY 协议的核心思想是多路复用,仅使用一个连接来传输一个网页中众多资源。它本质上并没有改变 HTTP 协议,只是将 HTTP 协议头通过 SPDY 来封装和传输。数据传输方式也是使用 TCP/IP 来传输。所以,SPDY 协议相对来说比较容易部署,服务器只需要插入 SPDY 协议的解释层,从 SPDY 的消息头中获取各个资源的 HTTP 头即可。其次,SPDY 协议必须建立在 SSL 层之上。</p>
<p>SPDY 特征如下:</p>
<ul>
<li>对于一条 SPDY 连接,并发的发起多少request没有任何限制</li>
<li>根据请求的特性和优先级,SPDY 可以调整这些资源请求的优先级,例如 Javascript 资源的优先级很高,服务器可以优先传输回复该类型的请求(这与管线化技术的 FIFO 不同)</li>
<li>对请求头使用压缩技术</li>
<li>支持 SPDY 协议的服务器在发送网页内容时,可以尝试发送一些信息给浏览器,告诉浏览器后面可能需要哪些资源,浏览器可以提前知道并决定是否需要下载。更极端的情况是,服务器可以主动发送资源。</li>
</ul>
<h2 id="webkit-内存缓存与磁盘缓存完整流程">Webkit 内存缓存与磁盘缓存完整流程</h2>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-7.png" alt="" /></p>
<p>第一次访问网页(这里以 https://www.baidu.com 为例),所有资源将从服务器获取:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-8.png" alt="" /></p>
<p>此时,理论上所有从服务器请求到的资源文件已经都存储到磁盘上了,并且满足上图条件中 JavaScript 文件和图片文件将保存到内存缓存池。</p>
<p>接着刷新网页:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-9.png" alt="" /></p>
<p>可以看到非动态加载的 JavaScript 文件和图片文件都时从内存缓存池中获取(from memory cache),而其他资源除了 xhr 请求,都是从磁盘缓存获取(form disc chace)。</p>
<p>最后,关闭网页,重新打开网页:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/网络栈-10.png" alt="" /></p>
<p>此时,所有的资源第一次都将从磁盘缓存获取。</p>
webkit学习笔记-(3)Webkit构架和模块
2018-05-27T00:00:00+00:00
https://blog.lisong.hn.cn/webkit/2018/05/27/webkit学习笔记-(3)Webkit构架和模块
<h2 id="webkit构架和模块">Webkit构架和模块</h2>
<h3 id="webkit构架">Webkit构架</h3>
<p>因为不同浏览器的需求,在Webkit中,一些代码是可以共享的,但是另一部分是不同的,这些不同的部分称为Webkit的移植(Ports)。</p>
<p>Webkit构架:</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-1.png" alt="" /></p>
<p>WebCore部分包含了被各个浏览器所使用的 <strong>Webkit 共享部分</strong>,这些都是加载和渲染网页的基础部分,他们必不可少,具体包括HTML解释器、CSS解释器、SVG、DOM、渲染树(renderObject,renderLayer),以及Inspector(调试器)。</p>
<p>JavaScriptCore 引擎是Webkit中默认的 Javascript 引擎。在Webkit中,对 Javascript 的调用是独立于引擎的。在 Google 的 Chrominum 中,它被替换成 V8 引擎。</p>
<p><strong>Webkit Ports</strong> 指的是 Webkit 中非共享部分,对于不同浏览器使用的 Webkit 来说,移植中的这些模块由于平台差异、依赖的第三方库和需求不同等方面原因,往往按照自己的方式来设计和实现,这就产生了移植部分,这是导致众多 Webkit 版本的行为并非一致的重要原因。这其中包括硬件加速构架、网络栈、视频解码、图片解码等。</p>
<p>嵌入式编程接口是提供给浏览器调用的。因为接口与具体的移植有关,所以有一个与浏览器相关的绑定层(可能不同的平台调用的同一个功能的 webkit 的接口不一样)。绑定层上面就是 Webkit 项目对外暴露的接口层。</p>
<h3 id="webkit源码目录">Webkit源码目录</h3>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-2.png" alt="" /><br /></p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-3.png" alt="" /></p>
<p>重要的目录包括 JavaScriptCore、Platform、WebCore、Webkit、Webkit2。JavaScriptCore 是 Webkit 渲染引擎的默认 Javascript 引擎。Platform 本来是 Chrominum 接口代码目录之一,现已被移除。WebCore 就是前面图中 WebCore 对应的相关代码。Webkit 和 Webkit2 是绑定和嵌入式接口层。</p>
<h2 id="基于-blink-的-chrominum-浏览器结构">基于 Blink 的 Chrominum 浏览器结构</h2>
<h3 id="chrominum-浏览器的架构及模块">Chrominum 浏览器的架构及模块</h3>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-4.png" alt="" /></p>
<p>“Content模块”和“Content Shell”将下面的渲染机制、安全机制和插件机制等隐藏起来,提供一个接口层。该接口层被 Chrominum 浏览器、Content Shell等调用。Chrominum 浏览器和 Content Shell 是构建在 Content API之上的两个浏览器。</p>
<p>即使没有 Content 模块,浏览器的开发者也可以在 Webkit的 Chrominum 移植上渲染网页内容,但是却没有办法获得沙箱模型、跨进程的 GPU加速机制、众多的 HTML5 功能,以为这些都是在 Content 层里实现的。</p>
<h4 id="多进程模型">多进程模型</h4>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-5.png" alt="" /></p>
<p>Chrominum 多进程模型特征:</p>
<ul>
<li>Browser 进程和页面的渲染时分开的,页面渲染进程的崩溃不会导致浏览器主界面的崩溃</li>
<li>每个网页是独立的进程,这保证了页面之间相互不影响</li>
<li>插件进程也是独立的,插件本身的问题不会影响到网页和主界面</li>
<li>GPU 硬件加速进程也是独立的,且只有一个 GPU 进程</li>
</ul>
<p>在 Android 平台上,GPU 进程演变成 Borwser 进程的一个线程。由于 Android 系统的局限性,Rneder 进程的数目会被严格限制,所以移动端浏览器引入了“影子”标签的概念,移动端浏览器会将后台的网页所使用的渲染设施都清除,当用户再次切换回来的时候,网页需要重新加载和渲染。</p>
<h4 id="browser-进程和-render-进程">Browser 进程和 Render 进程</h4>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-6.png" alt="" /></p>
<p>Webkit 黏附层的出现主要是因为 Chrominum 中的一些类型和 Webkit 内部不一致,所以需要一个简单的桥阶层。</p>
<p>Render 进程主要处理进程间通信,接受来自 Browser 进程的请求,并<strong>调用相应的 Webkit 接口层</strong>。同时,将 Webkit 的处理结果发送回去。</p>
<p>在 Browser 进程中,与 Render 进程相应的就是 RenderHost,其目的是处理同 Render 进程之间的通信,用来给 Render 进程发送请求并接收来自 Render 进程的结果。</p>
<h4 id="多线程模型">多线程模型</h4>
<p>每个进程内部都有很多线程,对于 Browser 进程,多线程的目的主要是为了保持用户界面的高度响应,保证 UI(Browser 主线程)线程不会被其他费时的操作阻碍从而影响对用户操作的响应。而在 Render 进程中,Chrominum 则不让其他操作阻止渲染线程的快速运行。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-7.png" alt="" /></p>
<p>网页渲染的过程在进程模型中的工作方式如下:</p>
<ul>
<li>Browser 进程收到用户的请求,首先有 UI 线程处理,而且将相应的任务给 IO 线程,IO 线程随即将该任务传递给 Render 进程。</li>
<li>Render 进程的 IO 线程经过简单的解释后交给<strong>渲染线程</strong>。渲染线程接受请求,加载网页并渲染网页,这其中可能需要 Browser 进程获取资源和需要 GPU 进程来帮助渲染。最后 Render 进程将结果由 IO 线程传递给 Browser 进程。</li>
<li>最后,Browser 进程接收到结果并将结果绘制出来。</li>
</ul>
<h4 id="content接口">Content接口</h4>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-10.png" alt="" /></p>
<p>Content 接口提供了一层对多进程进行渲染的抽象接口,其目标是要支持所有的 HTML5 功能、GPU 硬件加速功能和沙箱机制,这可以让 Content 接口的使用者们不需要很多的工作即可得到强大的能力。</p>
<p>Content 接口的相关代码按照功能分成六个部分,每个部分的接口一般可分成两类,第一类是调用者(Chrominum 浏览器、Content Shell等)调用的接口,另一类是调用者应该实现的<strong>回调接口</strong>,被 Content 接口的内部实现所调用。</p>
<h3 id="chrominum-content-接口代码结构">Chrominum Content 接口代码结构</h3>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-8.png" alt="" /></p>
<h2 id="webkit2">Webkit2</h2>
<h3 id="webkit2-架构及模块">Webkit2 架构及模块</h3>
<p>Webkit2 的思想同 Chrominum 类似,就是将渲染过程放在单独的进程中来完成,独立于用户界面。</p>
<p><img src="http://wanls4583.github.io/images/posts/webkit/webkit构架-9.png" alt="" /></p>
<p>“Web 进程”对应于 Chrominum 中的 Browser 进程,主要是渲染网页。“UI 进程”对应于 Chrominum 中的 Render 进程,接口就暴露在该进程,应用程序(浏览器)调用该接口即可。</p>
<h3 id="webkit-和-webkit2-嵌入式接口">Webkit 和 Webkit2 嵌入式接口</h3>
<p>Webkit 提供嵌入式接口,该接口表示其他程序可以将网页渲染嵌入在程序中作为其中的一部分。</p>
<p>在 Webkit 项目中,狭义 Webkit 的接口主要是与移植相关的 ewk_view 文件中的相关类。其主要思想是将网页的渲染结果作为用户界面的一个窗口部件,从这个角度上看,这跟其他的部件没有什么不同,区别在于它用来显示网页的内容。总结这些接口,按功能大致可以把所有接口分成6种类型:</p>
<ul>
<li>加载网页、获取加载进度、停止加载、重新加载等;</li>
<li>遍历前后浏览记录,可以前进、后退等;</li>
<li>网页的很多设置,例如缩放、主题、背景、编码等;</li>
<li>查找网页内容、高亮等;</li>
<li>触控事件、鼠标事件处理;</li>
<li>查看网页源代码、显示调试窗口等;</li>
</ul>
<p>Webkit2 接口不同于 Webkit 的接口,它们是不兼容的,不过目的都差不多,都是提供嵌入式的应用接口。</p>
<h3 id="比较-webkit2-和-chrominum-的多进程模型">比较 Webkit2 和 Chrominum 的多进程模型</h3>
<p>Webkit2 的多进程模型参考了 Chrominum 的模型和框架,也提供了多进程之上的接口层,但二者还是有一些区别的:</p>
<ul>
<li>Chrominum 使用的仍然是 Webkit 接口,而不是 Webkit2 接口,也就是说 Chrominum 是在 Webkit 接口之上构建的多进程架构;</li>
<li>Webkit2 的接口将多进程结构隐藏起来,这样可以让应用程序不必纠缠于内部的细节。但是,对 Chrominum 来说,它的主要目的时给 Chrominum 提供 Content 接口以便构建 Chrominum 浏览器,其本身目标不是提供嵌入式接口;</li>
<li>Chrominum 中每个进程都是从相同的二进制可执行文件启动,而基于 Webkit2 的进程则未必如此;</li>
</ul>
javascript实现三次贝塞尔曲线(cubic-bezier)
2018-05-26T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2018/05/26/javascript实现三次贝塞尔曲线(cubic-bezier)
<h2 id="贝塞尔曲线">贝塞尔曲线</h2>
<p>Bezier curve(贝塞尔曲线)是应用于二维图形应用程序的数学曲线。</p>
<p><strong>曲线定义:</strong>起始点、终止点(也称锚点)、控制点。通过调整控制点,贝塞尔曲线的形状会发生变化。</p>
<h3 id="一阶贝塞尔曲线">一阶贝塞尔曲线</h3>
<p><strong>公式:</strong>P<sub>0</sub><sup>1</sup> = (1-t)*P<sub>1</sub> + t*P<sub>1</sub> ,t∈[0,1]</p>
<p><br /><img src="http://wanls4583.github.io/images/posts/其他/贝塞尔-1.gif" alt="" /><br /></p>
<h3 id="二阶贝塞尔曲线">二阶贝塞尔曲线</h3>
<p><strong>公式:</strong>P<sub>0</sub><sup>2</sup> = (1-t)<sup>2</sup>*P<sub>0</sub> + 2*t*(1-t)*P<sub>1</sub> + t<sup>2</sup>*P<sub>2</sub> ,t∈[0,1]</p>
<p><br /><img src="http://wanls4583.github.io/images/posts/其他/贝塞尔-2.gif" alt="" /><br /></p>
<h3 id="三阶贝塞尔曲线">三阶贝塞尔曲线</h3>
<p><strong>公式:</strong>P<sub>0</sub><sup>3</sup> = (1-t)<sup>3</sup>*P<sub>0</sub> + 3*t*(1-t)<sup>2</sup>*P<sub>1</sub> + 3*(1-t)*t<sup>2</sup>*P<sub>2</sub> + t<sup>3</sup>*P<sub>3</sub> ,t∈[0,1]</p>
<p><br /><img src="http://wanls4583.github.io/images/posts/其他/贝塞尔-3.gif" alt="" /><br /></p>
<h3 id="通用公式">通用公式</h3>
<p><br /><img src="http://wanls4583.github.io/images/posts/其他/贝塞尔-4.gif" alt="" /><br /></p>
<h2 id="css3动画速度控制-cubic-bezier-x1y1x2y2">css3动画速度控制 cubic-bezier (x1,y1,x2,y2)</h2>
<p>CSS3动画速度的控制通过三次贝塞尔曲线函数实现,定义规则为 <code class="language-plaintext highlighter-rouge">cubic-bezier (x1,y1,x2,y2)</code></p>
<p>cubic-bezier 通过控制曲线上的四个点(起始点、终止点以及两个相互分离的中间点)来创造、编辑图形,绘制出一条光滑曲线并以曲线的状态来反映动画过程中速度的变化。</p>
<p><img src="http://wanls4583.github.io/images/posts/其他/贝塞尔-5.png" alt="" /></p>
<p>分别用 A,B,C,D 表示这四个点,其中起始点固定值为 A(0,0),终止点固定为 D(1,1)剩下的中间点 B(x1,y1),C(x2,y2) 也就是所要动态操控的两个点了,对应 cubic-bezier(x1,y1,x2,y2) 中的四个参数,通过改变 B,C 两点的坐标值来动态生成一条贝塞尔曲线表示动画中的速度变化。</p>
<h3 id="常用的缓动函数参数">常用的缓动函数参数</h3>
<table>
<thead>
<tr>
<th>name</th>
<th>cubic-bezier</th>
</tr>
</thead>
<tbody>
<tr>
<td>ease</td>
<td>.25,.1,.25,1</td>
</tr>
<tr>
<td>linear</td>
<td>0,0,1,1</td>
</tr>
<tr>
<td>ease-in</td>
<td>.42,0,1,1</td>
</tr>
<tr>
<td>ease-out</td>
<td>0,0,.58,1</td>
</tr>
<tr>
<td>ease-in-out</td>
<td>.42,0,.58,1</td>
</tr>
</tbody>
</table>
<p><img src="http://wanls4583.github.io/images/posts/其他/贝塞尔-6.png" alt="" /></p>
<h2 id="javascript-画三次贝塞尔曲线">Javascript 画三次贝塞尔曲线</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>cubic-bezier<span class="nt"></title></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nt">canvas</span><span class="p">{</span>
<span class="nl">transform</span><span class="p">:</span> <span class="n">rotateX</span><span class="p">(</span><span class="m">180deg</span><span class="p">);</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><canvas</span> <span class="na">width=</span><span class="s">"300"</span> <span class="na">height=</span><span class="s">"300"</span><span class="nt">></canvas></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="c1">//贝塞尔公式</span>
<span class="kd">function</span> <span class="nx">bsr</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="nx">p1</span><span class="p">,</span><span class="nx">p2</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">p0</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">p3</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="c1">//起点为0,终点为1</span>
<span class="c1">//3阶贝塞尔曲线公式</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">p0</span><span class="o">*</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">((</span><span class="mi">1</span><span class="o">-</span><span class="nx">t</span><span class="p">),</span><span class="mi">3</span><span class="p">)</span> <span class="o">+</span> <span class="mi">3</span><span class="o">*</span><span class="nx">p1</span><span class="o">*</span><span class="nx">t</span><span class="o">*</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">((</span><span class="mi">1</span><span class="o">-</span><span class="nx">t</span><span class="p">),</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="mi">3</span><span class="o">*</span><span class="nx">p2</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="nx">t</span><span class="p">)</span><span class="o">*</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="nx">p3</span><span class="o">*</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//cubic-bezier(.25,.1,.25,1)</span>
<span class="kd">function</span> <span class="nx">ease</span><span class="p">(</span><span class="nx">t</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">xScale</span> <span class="o">=</span> <span class="nx">bsr</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="mf">0.25</span><span class="p">,</span><span class="mf">0.25</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">yScale</span> <span class="o">=</span> <span class="nx">bsr</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="mf">0.1</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">xScale</span><span class="p">:</span> <span class="nx">xScale</span><span class="p">,</span>
<span class="na">yScale</span><span class="p">:</span> <span class="nx">yScale</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">obj</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">draw</span><span class="p">(</span><span class="nx">x1</span><span class="p">,</span><span class="nx">y1</span><span class="p">,</span><span class="nx">x2</span><span class="p">,</span><span class="nx">y2</span><span class="p">,</span><span class="nx">duration</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">startTime</span><span class="o">=</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">ctx</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">canvas</span><span class="dl">'</span><span class="p">).</span><span class="nx">getContext</span><span class="p">(</span><span class="dl">'</span><span class="s1">2d</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">preX</span><span class="o">=</span><span class="nx">x1</span><span class="p">,</span> <span class="nx">preY</span><span class="o">=</span><span class="nx">y1</span><span class="p">;</span>
<span class="nx">_draw</span><span class="p">();</span>
<span class="kd">function</span> <span class="nx">_draw</span><span class="p">(){</span>
<span class="nx">requestAnimationFrame</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">t</span> <span class="o">=</span> <span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span><span class="o">-</span><span class="nx">startTime</span><span class="p">)</span><span class="o">/</span><span class="nx">duration</span><span class="p">;</span> <span class="c1">//t∈[0,1]</span>
<span class="k">if</span><span class="p">(</span><span class="nx">t</span><span class="o">></span><span class="mi">1</span><span class="p">){</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">scale</span> <span class="o">=</span> <span class="nx">ease</span><span class="p">(</span><span class="nx">t</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="p">(</span><span class="nx">scale</span><span class="p">.</span><span class="nx">xScale</span><span class="o">*</span><span class="p">(</span><span class="nx">x2</span><span class="o">-</span><span class="nx">x1</span><span class="p">))</span><span class="o">>></span><span class="mi">0</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">y</span> <span class="o">=</span> <span class="p">(</span><span class="nx">scale</span><span class="p">.</span><span class="nx">yScale</span><span class="o">*</span><span class="p">(</span><span class="nx">y2</span><span class="o">-</span><span class="nx">y1</span><span class="p">))</span><span class="o">>></span><span class="mi">0</span><span class="p">;</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">beginPath</span><span class="p">();</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">moveTo</span><span class="p">(</span><span class="nx">preX</span><span class="p">,</span><span class="nx">preY</span><span class="p">);</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">lineTo</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="nx">y</span><span class="p">);</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">stroke</span><span class="p">();</span>
<span class="nx">preX</span> <span class="o">=</span> <span class="nx">x</span><span class="p">;</span>
<span class="nx">preY</span> <span class="o">=</span> <span class="nx">y</span><span class="p">;</span>
<span class="nx">_draw</span><span class="p">();</span>
<span class="p">})</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">draw</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">300</span><span class="p">,</span><span class="mi">300</span><span class="p">,</span><span class="mi">3000</span><span class="p">);</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>结果</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/其他/贝塞尔-7.png" alt="" /></p>
<h2 id="javascript-实现-cubic-bezier-缓动效果">Javascript 实现 cubic-bezier 缓动效果</h2>
<p>在 css3 中,如果动画定义了 cubic-bezier,则动画所做的事情就是把 x 轴当做时间比例,根据曲线得到 y 轴对应的值(这个 y 值代表了动画的完成度),并更新到动画对象中去。</p>
<p>即转化为以下问题:如何根据上述公式在已知 x 的情况下如何得到 y。</p>
<p>由上面的公式可知,已知 t 的情况下,可以计算出 x 和 y,因此最终问题转换程如何 在已知 x 的情况下 获得 t,也即解一元三次方程。解三次方程常用方法为牛顿迭代法,如果牛顿迭代发解不出可以用二分法来解。</p>
<p>不过还有更简单的方法,可以将 t 分成1000份,计算每一份所对应的 x,y 并保存到数组,之后只要根据 x 找到数组中最接的 x,即可直接获得 y。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>cubic-bezier<span class="nt"></title></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nc">.div</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">700px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">margin-bottom</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.div</span> <span class="nc">.bar</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">transform</span><span class="p">:</span> <span class="n">translateZ</span><span class="p">(</span><span class="m">0</span><span class="p">);</span>
<span class="nl">transition</span><span class="p">:</span> <span class="n">transform</span> <span class="m">3s</span><span class="p">;</span>
<span class="nl">transition-timing-function</span><span class="p">:</span> <span class="n">cubic-bezier</span><span class="p">(</span><span class="m">.42</span><span class="p">,</span><span class="m">0</span><span class="p">,</span><span class="m">.58</span><span class="p">,</span><span class="m">1</span><span class="p">);</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.bar.ani</span><span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="nl">transform</span><span class="p">:</span> <span class="n">translate3d</span><span class="p">(</span><span class="m">600px</span><span class="p">,</span><span class="m">0</span><span class="p">,</span><span class="m">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div"</span><span class="nt">><div</span> <span class="na">class=</span><span class="s">"bar"</span><span class="nt">></div></div></span>
<span class="nt"><canvas</span> <span class="na">width=</span><span class="s">"700"</span> <span class="na">height=</span><span class="s">"100"</span> <span class="na">id=</span><span class="s">"canvas"</span><span class="nt">></canvas></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="c1">//贝塞尔公式</span>
<span class="kd">function</span> <span class="nx">bsr</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="nx">p1</span><span class="p">,</span><span class="nx">p2</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">p0</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="nx">p3</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span><span class="c1">//起点为0,终点为1</span>
<span class="c1">//3阶贝塞尔曲线公式</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">p0</span><span class="o">*</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">((</span><span class="mi">1</span><span class="o">-</span><span class="nx">t</span><span class="p">),</span><span class="mi">3</span><span class="p">)</span> <span class="o">+</span> <span class="mi">3</span><span class="o">*</span><span class="nx">p1</span><span class="o">*</span><span class="nx">t</span><span class="o">*</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">((</span><span class="mi">1</span><span class="o">-</span><span class="nx">t</span><span class="p">),</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="mi">3</span><span class="o">*</span><span class="nx">p2</span><span class="o">*</span><span class="p">(</span><span class="mi">1</span><span class="o">-</span><span class="nx">t</span><span class="p">)</span><span class="o">*</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="mi">2</span><span class="p">)</span> <span class="o">+</span> <span class="nx">p3</span><span class="o">*</span><span class="nb">Math</span><span class="p">.</span><span class="nx">pow</span><span class="p">(</span><span class="nx">t</span><span class="p">,</span><span class="mi">3</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">scaleArr</span> <span class="o">=</span> <span class="p">[];</span>
<span class="c1">//计算并保存贝塞尔曲线坐标</span>
<span class="kd">function</span> <span class="nx">caculate</span><span class="p">(){</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o"><=</span><span class="mi">1</span><span class="p">;</span> <span class="nx">i</span><span class="o">+=</span><span class="mf">0.001</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">xScale</span> <span class="o">=</span> <span class="nx">bsr</span><span class="p">(</span><span class="nx">i</span><span class="p">,.</span><span class="mi">42</span><span class="p">,.</span><span class="mi">58</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">yScale</span> <span class="o">=</span> <span class="nx">bsr</span><span class="p">(</span><span class="nx">i</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">xScale</span><span class="p">:</span> <span class="nx">xScale</span><span class="p">,</span>
<span class="na">yScale</span><span class="p">:</span> <span class="nx">yScale</span>
<span class="p">};</span>
<span class="nx">scaleArr</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">obj</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//根据x坐标获取y坐标</span>
<span class="kd">function</span> <span class="nx">solve</span><span class="p">(</span><span class="nx">xScale</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">diff</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o"><</span><span class="mi">1000</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">_x</span> <span class="o">=</span> <span class="nx">scaleArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">xScale</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">_diff</span> <span class="o">=</span> <span class="nb">Math</span><span class="p">.</span><span class="nx">abs</span><span class="p">(</span><span class="nx">_x</span><span class="o">-</span><span class="nx">xScale</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">_diff</span> <span class="o"><</span> <span class="nx">diff</span><span class="p">){</span>
<span class="nx">diff</span> <span class="o">=</span> <span class="nx">_diff</span><span class="p">;</span>
<span class="nx">result</span> <span class="o">=</span> <span class="nx">scaleArr</span><span class="p">[</span><span class="nx">i</span><span class="p">].</span><span class="nx">yScale</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">draw</span><span class="p">(</span><span class="nx">x1</span><span class="p">,</span><span class="nx">y1</span><span class="p">,</span><span class="nx">x2</span><span class="p">,</span><span class="nx">y2</span><span class="p">,</span><span class="nx">duration</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">startTime</span><span class="o">=</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">ctx</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">#canvas</span><span class="dl">'</span><span class="p">).</span><span class="nx">getContext</span><span class="p">(</span><span class="dl">'</span><span class="s1">2d</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">diff</span> <span class="o">=</span> <span class="nx">duration</span><span class="o">/</span><span class="mi">1000</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">start</span> <span class="o">=</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">();</span>
<span class="nx">_draw</span><span class="p">();</span> <span class="c1">//canvas动画</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">querySelector</span><span class="p">(</span><span class="dl">'</span><span class="s1">.bar</span><span class="dl">'</span><span class="p">).</span><span class="nx">className</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">bar ani</span><span class="dl">'</span><span class="p">;</span> <span class="c1">//css3动画</span>
<span class="kd">function</span> <span class="nx">_draw</span><span class="p">(){</span>
<span class="nx">requestAnimationFrame</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">xScale</span> <span class="o">=</span> <span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">now</span><span class="p">()</span><span class="o">-</span><span class="nx">start</span><span class="p">)</span><span class="o">/</span><span class="nx">duration</span><span class="p">;</span> <span class="c1">//x轴时间变量,xScale∈[0,1]</span>
<span class="k">if</span><span class="p">(</span><span class="nx">xScale</span> <span class="o">></span> <span class="mi">1</span><span class="p">){</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">yScale</span> <span class="o">=</span> <span class="nx">solve</span><span class="p">(</span><span class="nx">xScale</span><span class="p">);</span> <span class="c1">//动画完成度</span>
<span class="kd">var</span> <span class="nx">x</span> <span class="o">=</span> <span class="p">(</span><span class="nx">yScale</span><span class="o">*</span><span class="p">(</span><span class="nx">x2</span><span class="o">-</span><span class="nx">x1</span><span class="p">)</span><span class="o">+</span><span class="nx">x1</span><span class="p">)</span><span class="o">>></span><span class="mi">0</span><span class="p">;</span> <span class="c1">//x轴动画完</span>
<span class="kd">var</span> <span class="nx">y</span> <span class="o">=</span> <span class="p">(</span><span class="nx">yScale</span><span class="o">*</span><span class="p">(</span><span class="nx">y2</span><span class="o">-</span><span class="nx">y1</span><span class="p">)</span><span class="o">+</span><span class="nx">y1</span><span class="p">)</span><span class="o">>></span><span class="mi">0</span><span class="p">;</span> <span class="c1">//y轴动画</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">clearRect</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">800</span><span class="p">,</span><span class="mi">300</span><span class="p">);</span>
<span class="nx">ctx</span><span class="p">.</span><span class="nx">fillRect</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span><span class="nx">y</span><span class="p">,</span><span class="mi">100</span><span class="p">,</span><span class="mi">100</span><span class="p">);</span> <span class="c1">//画矩形</span>
<span class="nx">_draw</span><span class="p">();</span>
<span class="p">})</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">caculate</span><span class="p">();</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">draw</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">600</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">3000</span><span class="p">);</span> <span class="c1">//画矩形</span>
<span class="p">},</span><span class="mi">60</span><span class="p">)</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>结果</strong></p>
<p><img src="http://wanls4583.github.io/images/posts/其他/贝塞尔-8.gif" alt="" /></p>
<p>从结果可以看出,只要贝塞尔参数相同,用 javascript 可以实现和 css3 相同的效果。</p>
<p>参考:</p>
<p><a href="https://blog.csdn.net/zhaozjc112/article/details/52909172">https://blog.csdn.net/zhaozjc112/article/details/52909172</a></p>
<p><a href="https://www.cnblogs.com/hnfxs/p/3148483.html">https://www.cnblogs.com/hnfxs/p/3148483.html</a></p>
webkit学习笔记-(2)HTML网页和结构
2018-05-25T00:00:00+00:00
https://blog.lisong.hn.cn/webkit/2018/05/25/webkit学习笔记-(2)HTML网页和结构
<h2 id="网页结构">网页结构</h2>
<h3 id="框结构">框结构</h3>
<p>框结构用来对网页的布局进行分割,将网页分成几个框,例如 frameset,frame,iframe 等元素都会形成新的框。每一个框结构包含一个 HTML 文档,最简单的框结构网页就是单一的框,当然,一个网页中也可以有多个框。</p>
<p><img src="https://wanls4583.github.io/images/posts/webkit/网页结构-1.png" alt="" /></p>
<h3 id="层次结构">层次结构</h3>
<p>网页的层次结构是指网页中的元素可能分布在不同的层次中,也就是说某些元素可能不同于它的父元素所在的层,因为某些原因,Webkit 需要为该元素和它的子女建立一个新层。</p>
<h2 id="webkit的网页渲染过程">Webkit的网页渲染过程</h2>
<p>在网页中,我们把当前可见的区域称之为视图。</p>
<p>Webkit的渲染过程如下图所示:</p>
<p><img src="https://wanls4583.github.io/images/posts/webkit/网页结构-2.png" alt="" /></p>
<p>加载完 HTML 文档后,渲染引擎开始创建DOM树,如果解析的过程中需要加载Javascript文件,则会停止当前 DOM 树的创建,直到 Javascript 文件加载并执行完成后才继续后面的DOM的创建。</p>
<p>HTML文档下载完成时会发出“DOMContent”事件,当HTML依赖的所有资源都加载完后会发出“onload”事件。</p>
<p>在解析 HTML 文档时,如果遇到 CSS 资源或者内联样式,Webkit 将会调用CSS解释器构建 CSSOM 树。随后,Webkit 在 DOM 树上附加上样式信息,构建出 RnederObject 树。RenderObject 树创建的同时,Webkit 会根据网页的层次结构创建 RenderLayer 树,同时创建一个虚拟的绘图上下文。</p>
<p><img src="https://wanls4583.github.io/images/posts/webkit/网页结构-3.png" alt="" /></p>
<p>图形上下文是一个与平台无关的抽象类,它将每个绘图操作桥接到不同的具体实现类(系统的图形库),最后由实现类来完成最终的绘制。</p>
webkit学习笔记-(1)浏览器和浏览器内核
2018-05-24T00:00:00+00:00
https://blog.lisong.hn.cn/webkit/2018/05/24/webkit学习笔记-(1)浏览器和浏览器内核
<h2 id="浏览器">浏览器</h2>
<h3 id="浏览器发展史">浏览器发展史</h3>
<table>
<thead>
<tr>
<th>Year</th>
<th>Browser</th>
<th>Who</th>
</tr>
</thead>
<tbody>
<tr>
<td>20世纪80年代后期90年代初</td>
<td>WorldWideWeb(后改名为Nexus)</td>
<td>Berners-Lee(W3C理事)</td>
</tr>
<tr>
<td>1993</td>
<td>Mosaic(发展为大名鼎鼎的Netscape)</td>
<td>Marc Andreessen</td>
</tr>
<tr>
<td>1995</td>
<td>IE</td>
<td>微软</td>
</tr>
<tr>
<td>2003</td>
<td>Safari(2005年释放了重要部分的源代码,发起开源项目Webkit)</td>
<td>苹果公司</td>
</tr>
<tr>
<td>2004</td>
<td>Firefox</td>
<td>Mozilla</td>
</tr>
<tr>
<td>2008</td>
<td>Chrome(以Webkit为内核,创建了Chrominum项目,并在此基础上发布了Chrome)</td>
<td>Google</td>
</tr>
</tbody>
</table>
<h4 id="chrominum">Chrominum</h4>
<p>Chrominum 本身就是一个浏览器,而不是Chrome浏览器的内核,Chrome浏览器一般选择Chrominum的稳定版本作为它的基础。</p>
<h4 id="格局">格局</h4>
<p>对于桌面系统而言,IE、Firefox、Chrome占据了市场90%的浏览器份额。而在移动端,由于苹果的IOS系统和谷歌的Android系统占据了绝对领先的地位,因而基本上移动端的浏览器都是基于Webkit。</p>
<h3 id="html">HTML</h3>
<p>HTML1.0由著名的Berners-Lee于1991年提出,此后经历了多次版本更新,直到1997年4.0版本和1999年的4.01版本。</p>
<p>具有划时代意义的HTML5技术在2012年由W3C和WHATWG推荐为候选规范。HTML5包含了一系列标准,一共包含10个大的分类</p>
<table>
<tbody>
<tr>
<td>离线</td>
<td>Apllication cache,Local storage,Index DB,在线/离线事件</td>
</tr>
<tr>
<td>存储</td>
<td>Apllication cache,Local storage,Index DB</td>
</tr>
<tr>
<td>连接</td>
<td>Web Socket,server-sent事件</td>
</tr>
<tr>
<td>文件访问</td>
<td>File API,File System,FileWriter,ProgressEvent</td>
</tr>
<tr>
<td>语义</td>
<td>各种的新的元素,如Header,Footer等</td>
</tr>
<tr>
<td>音频和视频</td>
<td>HTML5 Video,Web Audio,WebRTC,Video track</td>
</tr>
<tr>
<td>3D和图像</td>
<td>Canvas 2D,3D CSS变换,WebGL,SVG等</td>
</tr>
<tr>
<td>展示</td>
<td>CSS 2D/3D变换,转换(transition),WebFonts等</td>
</tr>
<tr>
<td>性能</td>
<td>Web Worker,HTTP caching等</td>
</tr>
<tr>
<td>其他</td>
<td>触控和鼠标,Shadow DOM,CSS masking</td>
</tr>
</tbody>
</table>
<h3 id="浏览器用户代理user-agent">浏览器用户代理(User-agent)</h3>
<p>用户代理主要用来表明浏览器的身份。因为某种浏览器的流行,很多站点会根据这种浏览器来定制特定内容,当其他浏览器也需要相同的网页时,就只能通过在User-agent里添加上此种浏览器的信息来冒充此种浏览器。</p>
<h2 id="浏览器内核及特性">浏览器内核及特性</h2>
<p>浏览器内核通常也被称为渲染引擎,渲染引擎能够将HTML/CSS/JS文本及其相应的资源转换成图像结果。</p>
<p>目前,主要浏览器内核包括Trident(IE),Gecko(Firefox),Webkit。2013年,Google宣布了Blink内核,它其实时从Webkit复制出去的。</p>
<h3 id="内核特征">内核特征</h3>
<p>渲染引擎主要包括四个模块:</p>
<ul>
<li>HTML解释器</li>
<li>CSS解释器</li>
<li>布局</li>
<li>Javascript引擎</li>
</ul>
<p><img src="https://wanls4583.github.io/images/posts/webkit/浏览器和浏览器内核-1.png" alt="" /></p>
<p>一般来说,渲染引擎会内置一个默认的Javascript引擎,不过大多数浏览器会将其替换,所以严格来说,Javascript引擎并不属于内核的一部分。Javscript引擎能够解释Javascript代码并通过DOM接口和CSSOM接口来修改网页的内容和样式。</p>
<p>以上这些模块依赖很多系统内置的模块,包括网络、存储、2D/3D图像、音视视频和图形解码器等。如此说来,实际上,渲染引擎应该还包括如何使用这些依赖模块的部分。</p>
<p>当DOM建立的时候,渲染引擎接收来自CSS解释器的信息,构建一个新的内部绘图模型。该模型由布局模块计算模型内各个元素的位置和大小信息,最后调用绘图模块完成网页的绘制。</p>
<h2 id="webkit">Webkit</h2>
<p>2001年,苹果宣布从KHTML的源代码树中复制代码出来,成立了一个新的项目,这就时大名鼎鼎的Webkit。苹果公司在2005年将Webkit项目开源。</p>
<p>“Webkit”这个单词其实可以表示成两种含义,姑且称之为广义Webkit和狭义Webkit。广义Webkit指的是整个Webkit项目,狭义Webkit指的是Webcore(包含HTML解释器,CSS解释器,布局模块)和Javascript引擎之上的一层绑定和嵌入式编程接口,可以被各种浏览器调用。</p>
<p><img src="https://wanls4583.github.io/images/posts/webkit/浏览器和浏览器内核-1.png" alt="" /></p>
<p>Webkit被很很多浏览器所实现,每个移植的HTML5规范支持不尽相同,所以,尽管都是使用Webkit,但还是可能对兼容性带来很大的挑战。</p>
<h3 id="webkit和webkit2">Webkit和WebKit2</h3>
<p>Webkit2也是一个狭义上的绑定和接口层,但是Webkit2不是Webkit绑定和接口层的简单升级,而是一组支持新架构(多进程)的全新绑定和接口层。</p>
<p>20104月,苹果宣布了Webkit2,目标就是抽象出一组新的编程接口,该接口和调用者代码与网页的渲染工作代码不在同一个进程,这显然有了Chrominum多进程的优点。而且,Webkit接口的使用者不需要理解和接触背后的多进程和进程间通信等复杂机制,Webkit2部分代码也属于Webkit项目。Webkit2进程结构模型至少包含两个进程,其一时UI进程(绑定和接口层所在的进程,也就是浏览器的UI进程),其二时Web进程(网页渲染所在的进程)。下面时Webkit2和Chrominum的进程模型图。</p>
<p><img src="https://wanls4583.github.io/images/posts/webkit/浏览器和浏览器内核-2.png" alt="https://trac.webkit.org/wiki/WebKit2" /></p>
<p><img src="https://wanls4583.github.io/images/posts/webkit/浏览器和浏览器内核-3.png" alt="https://trac.webkit.org/wiki/WebKit2" /></p>
<p>通过API boundary可以看出来,基于Chrominum项目框架来开发一个浏览器,开发者需要自己处理多进程和多进程之间的通信,而使用Webkit2架构则不需要。</p>
<h3 id="blink">Blink</h3>
<p>Blink时Chrominum浏览器的内核,最初时用从Webkit项目复制过来的。</p>
<p>Blink有一个大胆的想法,想要将DOM树引入Javascript引擎中(目前应该还未实现)。目前DOM树和Javascript引擎是分开的,在DOM树与Javascript引擎中间有一个桥阶层,这意味着Javascript引擎访问DOM树需要较高的代价。</p>
vuex浅析
2018-05-15T00:00:00+00:00
https://blog.lisong.hn.cn/vue/2018/05/15/vuex浅析
<h3 id="vuex">Vuex</h3>
<p>每一个 Vuex 应用的核心就是 <code class="language-plaintext highlighter-rouge">store</code>(仓库)。“store”基本上就是一个容器,它包含着你的应用中大部分的状态 (<code class="language-plaintext highlighter-rouge">state</code>)。<code class="language-plaintext highlighter-rouge">Vuex</code> 和单纯的全局对象有以下两点不同:</p>
<ul>
<li>Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 <code class="language-plaintext highlighter-rouge">store </code>中的状态发生变化,那么相应的组件也会相应地得到高效更新。</li>
<li>你不能直接改变 <code class="language-plaintext highlighter-rouge">store</code> 中的状态。改变 <code class="language-plaintext highlighter-rouge">store</code> 中的状态的唯一途径就是显式地提交 (<code class="language-plaintext highlighter-rouge">commit</code>) <code class="language-plaintext highlighter-rouge">mutation</code>。这样使得我们可以方便地跟踪每一个状态的变化,从而让我们能够实现一些工具帮助我们更好地了解我们的应用。</li>
</ul>
<p>以上是官方对 Vuex 的定义,需要注意的时第二点(改变<code class="language-plaintext highlighter-rouge">store</code>中的状态的唯一途径时显示的提交<code class="language-plaintext highlighter-rouge">commit</code>),这只是该工具推荐的使用原则,但是 Vuex 并没有采取任何的措施去强制开发者必须这么做。之所以要求开发者这么做只是出于框架的核心概念(也是所有状态管理工具的核心原则),只有这么做才能方便状态的追踪管理,否则就失去了状态管理框架的意义。</p>
<p>基本使用:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>vuex-demo<span class="nt"></title></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"</span><span class="nt">></script></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vuex@3.0.1/dist/vuex.min.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
{{$store.state.count}},{{count}}
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">Store</span><span class="p">({</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">count</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">mutations</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">num</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">count</span> <span class="o">+=</span> <span class="nx">num</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">count add </span><span class="dl">'</span><span class="p">,</span> <span class="nx">num</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="kd">var</span> <span class="nx">vue</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span><span class="p">,</span>
<span class="na">store</span><span class="p">:</span> <span class="nx">store</span><span class="p">,</span>
<span class="na">computed</span><span class="p">:</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">mapState</span><span class="p">([</span><span class="dl">'</span><span class="s1">count</span><span class="dl">'</span><span class="p">])</span> <span class="c1">//属性映射</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vue</span><span class="p">.</span><span class="nx">$store</span> <span class="o">===</span> <span class="nx">store</span><span class="p">);</span> <span class="c1">//true,vue实例的$store属性是store对象的一个引用</span>
<span class="cm">/*store本质和vue组件的data对象一样,是一个响应式的数据对象,只不过store是全局的,
虽然可以直接操作store中的状态,但不到万不得已,千万不要这么做,这样会失去对状态的跟踪*/</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="o">++</span><span class="p">;</span>
<span class="cm">/*正确的使用方法时调用mutation去改变状态*/</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span> <span class="mi">2</span><span class="p">);</span> <span class="c1">//调用mutation里面的方法</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/vue/vuex-1.png" alt="" /></p>
<h3 id="getters">getters</h3>
<p>getters属性主要用来过滤一些数据,如果不需要过滤,直接使用state访问更加方便。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
<span class="nt"><div></span>{{$store.getters.getCountAddOne}}<span class="nt"></div></span>
<span class="nt"><div></span>{{getCountAddOne}}<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">Store</span><span class="p">({</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">count</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">getters</span><span class="p">:</span> <span class="p">{</span>
<span class="nx">getCountAddOne</span><span class="p">(</span><span class="nx">state</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="o">+</span><span class="mi">1</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="kd">var</span> <span class="nx">vue</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span><span class="p">,</span>
<span class="na">store</span><span class="p">:</span> <span class="nx">store</span><span class="p">,</span>
<span class="na">computed</span><span class="p">:</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">mapGetters</span><span class="p">([</span><span class="dl">'</span><span class="s1">getCountAddOne</span><span class="dl">'</span><span class="p">])</span> <span class="c1">//将store中的getter映射到局部计算属性</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Vuex</span><span class="p">.</span><span class="nx">mapGetters</span><span class="p">([</span><span class="dl">'</span><span class="s1">getCountAddOne</span><span class="dl">'</span><span class="p">]))</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/vue/vuex-2.png" alt="" /></p>
<h3 id="mutation">Mutation</h3>
<p><code class="language-plaintext highlighter-rouge">mutation</code>用来更改状态,官方规定<code class="language-plaintext highlighter-rouge">mutation</code>方法必须时同步方法,因为对于每一条<code class="language-plaintext highlighter-rouge">mutation</code>被记录,<code class="language-plaintext highlighter-rouge">devtools</code> 都需要捕捉到前一状态和后一状态的快照这样当状态改变后,这样就可以轻松的使用<code class="language-plaintext highlighter-rouge">devtools</code>查看状态的变化了。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
<span class="nt"><div></span>{{count}}<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">Store</span><span class="p">({</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">count</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">mutations</span><span class="p">:</span> <span class="p">{</span>
<span class="nx">add</span><span class="p">(</span><span class="nx">state</span><span class="p">){</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="o">++</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">del</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="nx">num</span><span class="p">){</span> <span class="c1">//可以接受参数</span>
<span class="k">if</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">num</span> <span class="o">==</span> <span class="dl">'</span><span class="s1">object</span><span class="dl">'</span><span class="p">){</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="o">-=</span><span class="nx">num</span><span class="p">.</span><span class="nx">num</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="o">-=</span><span class="nx">num</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="kd">var</span> <span class="nx">vue</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span><span class="p">,</span>
<span class="na">store</span><span class="p">:</span> <span class="nx">store</span><span class="p">,</span>
<span class="na">computed</span><span class="p">:</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">mapState</span><span class="p">([</span><span class="dl">'</span><span class="s1">count</span><span class="dl">'</span><span class="p">]),</span>
<span class="na">methods</span><span class="p">:</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">mapMutations</span><span class="p">([</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">])</span> <span class="c1">//映射mutation方法</span>
<span class="p">})</span>
<span class="nx">vue</span><span class="p">.</span><span class="nx">add</span><span class="p">();</span> <span class="c1">//使用映射后的方法</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vue</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span> <span class="c1">//2</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">del</span><span class="dl">'</span><span class="p">,</span><span class="mi">2</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vue</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span> <span class="c1">//0</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">commit</span><span class="p">({</span> <span class="c1">//可以使用对象风格去调用mutation</span>
<span class="na">type</span><span class="p">:</span> <span class="dl">'</span><span class="s1">del</span><span class="dl">'</span><span class="p">,</span>
<span class="na">num</span><span class="p">:</span> <span class="mi">2</span>
<span class="p">});</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vue</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span> <span class="c1">//-2</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
</code></pre></div></div>
<h3 id="action">Action</h3>
<p><code class="language-plaintext highlighter-rouge">action</code>类似于<code class="language-plaintext highlighter-rouge">mutation</code>,不同在于:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">action</code>提交的是<code class="language-plaintext highlighter-rouge">mutation</code>,而不是直接变更状态</li>
<li><code class="language-plaintext highlighter-rouge">action</code>可以包含任意异步操作</li>
</ul>
<p>事实上在 vuex 里面<code class="language-plaintext highlighter-rouge">actions</code>只是一个架构性的概念,并不是必须的,说到底只是一个函数,你在里面想干嘛都可以,只要最后触发<code class="language-plaintext highlighter-rouge">mutation</code>就行。异步竞态怎么处理那是用户自己的事情。vuex 真正限制你的只有<code class="language-plaintext highlighter-rouge">mutation</code>必须是同步的这一点(在<code class="language-plaintext highlighter-rouge">redux</code>里面就好像<code class="language-plaintext highlighter-rouge">reducer</code>必须同步返回下一个状态一样)。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
<span class="nt"><div></span>{{count}}<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">Store</span><span class="p">({</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">count</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">mutations</span><span class="p">:</span> <span class="p">{</span>
<span class="nx">add</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="nx">num</span><span class="p">){</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="o">+=</span><span class="nx">num</span><span class="p">;</span>
<span class="p">},</span>
<span class="nx">del</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="nx">num</span><span class="p">){</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">count</span><span class="o">-=</span><span class="nx">num</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">actions</span><span class="p">:</span> <span class="p">{</span>
<span class="nx">add</span><span class="p">(</span><span class="nx">store</span><span class="p">,</span><span class="nx">num</span><span class="p">){</span>
<span class="k">return</span> <span class="k">new</span> <span class="nb">Promise</span><span class="p">((</span><span class="nx">resolve</span><span class="p">)</span><span class="o">=></span><span class="p">{</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="nx">num</span><span class="p">);</span>
<span class="nx">resolve</span><span class="p">();</span>
<span class="p">},</span><span class="mi">1000</span><span class="p">);</span>
<span class="p">})</span>
<span class="p">},</span>
<span class="nx">del</span><span class="p">(</span><span class="nx">state</span><span class="p">,</span><span class="nx">num</span><span class="p">){</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">del</span><span class="dl">'</span><span class="p">,</span><span class="nx">num</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vue</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span> <span class="c1">//2</span>
<span class="p">},</span><span class="mi">500</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="kd">var</span> <span class="nx">vue</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span><span class="p">,</span>
<span class="na">store</span><span class="p">:</span> <span class="nx">store</span><span class="p">,</span>
<span class="na">computed</span><span class="p">:</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">mapState</span><span class="p">([</span><span class="dl">'</span><span class="s1">count</span><span class="dl">'</span><span class="p">]),</span>
<span class="na">methods</span><span class="p">:</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">mapActions</span><span class="p">([</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">])</span> <span class="c1">//映射action方法</span>
<span class="p">})</span>
<span class="nx">vue</span><span class="p">.</span><span class="nx">add</span><span class="p">(</span><span class="mi">2</span><span class="p">).</span><span class="nx">then</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="dl">'</span><span class="s1">del</span><span class="dl">'</span><span class="p">,</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vue</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span> <span class="c1">//3</span>
<span class="p">});</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vue</span><span class="p">.</span><span class="nx">count</span><span class="p">);</span> <span class="c1">//1</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
</code></pre></div></div>
<h3 id="module">Module</h3>
<p>如果项目很大,可以把状态模块化,不同模块保存不同的状态信息,实例化<code class="language-plaintext highlighter-rouge">store</code>时通过<code class="language-plaintext highlighter-rouge">modules</code>属性引用不同的模块。默认情况下,所有模块的<code class="language-plaintext highlighter-rouge">mutation</code>,<code class="language-plaintext highlighter-rouge">getters</code>,<code class="language-plaintext highlighter-rouge">actions</code>都挂载在<code class="language-plaintext highlighter-rouge">store</code>实例下。</p>
<h4 id="基本使用">基本使用</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
{{$store.state.modA.a}},{{$store.state.modB.b}}
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">modA</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">a</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">mutations</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">num</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="c1">//这里的state代表的是modA的局部state</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">a</span> <span class="o">+=</span> <span class="nx">num</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">a add </span><span class="dl">'</span><span class="p">,</span> <span class="nx">num</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">actions</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">context</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="c1">//对于模块内部的 mutation 和 getter,接收的第一个参数是模块的局部状态对象</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">context</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">a</span><span class="p">,</span><span class="nx">context</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">b</span><span class="p">)</span> <span class="c1">//2 undefined</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="nx">context</span><span class="p">.</span><span class="nx">rootState</span><span class="p">.</span><span class="nx">num</span><span class="p">);</span> <span class="c1">//这里还是会调用所有模块名为add的mutation方法,rootState代表根状态对象</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">modB</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">b</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">mutations</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">num</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">b</span> <span class="o">+=</span> <span class="nx">num</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">b add </span><span class="dl">'</span><span class="p">,</span> <span class="nx">num</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">Store</span><span class="p">({</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">num</span><span class="p">:</span> <span class="mi">10</span>
<span class="p">},</span>
<span class="na">modules</span><span class="p">:</span> <span class="p">{</span>
<span class="na">modA</span><span class="p">:</span> <span class="nx">modA</span><span class="p">,</span>
<span class="na">modB</span><span class="p">:</span> <span class="nx">modB</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="kd">var</span> <span class="nx">vue</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span><span class="p">,</span>
<span class="na">store</span><span class="p">:</span> <span class="nx">store</span>
<span class="p">})</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="c1">//在没有命名空间的情况下,会调用所有名为add的mutation方法</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">store</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">modA</span><span class="p">.</span><span class="nx">a</span><span class="p">);</span> <span class="c1">//2</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">)</span> <span class="c1">//在没有命名空间的情况下,会调用所有名为add的action方法</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">store</span><span class="p">.</span><span class="nx">state</span><span class="p">.</span><span class="nx">modA</span><span class="p">.</span><span class="nx">a</span><span class="p">);</span> <span class="c1">//12</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/vue/vuex-3.png" alt="" /></p>
<h4 id="命名空间">命名空间</h4>
<p>通过添加 <code class="language-plaintext highlighter-rouge">namespaced: true</code> 的方式使其成为带命名空间的模块。当模块被注册后,它的所有 <code class="language-plaintext highlighter-rouge">getter</code>、<code class="language-plaintext highlighter-rouge">action</code> 及 <code class="language-plaintext highlighter-rouge">mutation</code> 都会自动根据模块注册的路径调整命名。</p>
<p>示例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
{{$store.state.modA.a}},{{$store.state.modB.b}}
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">modA</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">namespaced</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> <span class="c1">//有了命名空间后,该模块下的所有mutation,getters,actions都将局部化</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">a</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">mutations</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">num</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">a</span> <span class="o">+=</span> <span class="nx">num</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">a add </span><span class="dl">'</span><span class="p">,</span> <span class="nx">num</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">actions</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">context</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modA add action</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="nx">context</span><span class="p">.</span><span class="nx">rootState</span><span class="p">.</span><span class="nx">num</span><span class="p">);</span> <span class="c1">//有了命名空间后,这里只会调用本modA下的mutation</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">context.commit('add',context.rootState.num,{root:true})(在命名空间模块里调用全局mutation)</span><span class="dl">"</span><span class="p">);</span>
<span class="c1">//通过加上第三个参数{root:true},这里会调用除了命名模块之外所有名字为add的mutation</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="nx">context</span><span class="p">.</span><span class="nx">rootState</span><span class="p">.</span><span class="nx">num</span><span class="p">,{</span><span class="na">root</span><span class="p">:</span><span class="kc">true</span><span class="p">});</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">context.dispatch('add',null,{root:true})(在命名空间模块里分发全局action)</span><span class="dl">"</span><span class="p">);</span>
<span class="c1">//通过加上第三个参数{root:true},这里会调用除了命名模块之外所有名字为add的action</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="kc">null</span><span class="p">,{</span><span class="na">root</span><span class="p">:</span><span class="kc">true</span><span class="p">});</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">modB</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">b</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">mutations</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">num</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">b</span> <span class="o">+=</span> <span class="nx">num</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">b add </span><span class="dl">'</span><span class="p">,</span> <span class="nx">num</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">actions</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">context</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modB add action</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="nx">context</span><span class="p">.</span><span class="nx">rootState</span><span class="p">.</span><span class="nx">num</span><span class="p">);</span> <span class="c1">//这里会调用除了命名模块之外所有名字为add的mutation</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">modC</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">c</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">},</span>
<span class="na">mutations</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">state</span><span class="p">,</span> <span class="nx">num</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="nx">state</span><span class="p">.</span><span class="nx">c</span> <span class="o">+=</span> <span class="nx">num</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">c add </span><span class="dl">'</span><span class="p">,</span> <span class="nx">num</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">actions</span><span class="p">:</span> <span class="p">{</span>
<span class="na">add</span><span class="p">:</span> <span class="p">(</span><span class="nx">context</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span> <span class="c1">//</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">modC add action</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">context</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="nx">context</span><span class="p">.</span><span class="nx">rootState</span><span class="p">.</span><span class="nx">num</span><span class="p">);</span> <span class="c1">//这里会调用除了命名模块之外所有名字为add的mutation</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">store</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vuex</span><span class="p">.</span><span class="nx">Store</span><span class="p">({</span>
<span class="na">state</span><span class="p">:</span> <span class="p">{</span>
<span class="na">num</span><span class="p">:</span> <span class="mi">10</span>
<span class="p">},</span>
<span class="na">modules</span><span class="p">:</span> <span class="p">{</span>
<span class="na">modA</span><span class="p">:</span> <span class="nx">modA</span><span class="p">,</span>
<span class="na">modB</span><span class="p">:</span> <span class="nx">modB</span><span class="p">,</span>
<span class="na">modC</span><span class="p">:</span> <span class="nx">modC</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="kd">var</span> <span class="nx">vue</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span><span class="p">,</span>
<span class="na">store</span><span class="p">:</span> <span class="nx">store</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">store.commit('add',1)</span><span class="dl">"</span><span class="p">)</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="c1">//这里会调用除了命名模块之外所有名字为add的mutation</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">store.commit('modA/add',1)</span><span class="dl">"</span><span class="p">)</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">commit</span><span class="p">(</span><span class="dl">'</span><span class="s1">modA/add</span><span class="dl">'</span><span class="p">,</span><span class="mi">1</span><span class="p">)</span> <span class="c1">//调用modA中名为add的mutation</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">store.dispatch('add')</span><span class="dl">"</span><span class="p">)</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">)</span> <span class="c1">//这里会调用除了命名模块之外所有名字为add的action</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">store.dispatch('modA/add')</span><span class="dl">"</span><span class="p">)</span>
<span class="nx">store</span><span class="p">.</span><span class="nx">dispatch</span><span class="p">(</span><span class="dl">'</span><span class="s1">modA/add</span><span class="dl">'</span><span class="p">)</span> <span class="c1">//调用modA中名为add的action</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/vue/vuex-4.png" alt="" /></p>
python(面向对象高级特性)
2018-05-11T00:00:00+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/05/11/python(面向对象高级特性)
<h3 id="slots"><strong>slots</strong></h3>
<p>python类似js,是一门动态语言,可以动态的给类或者实例添加方法和属性,给类添加的方法和属性可以应用多所有该类的实例。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="k">pass</span>
<span class="n">Class</span><span class="p">.</span><span class="n">name</span><span class="o">=</span><span class="s">'i am class'</span>
<span class="n">obj</span><span class="o">=</span><span class="n">Class</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">obj</span><span class="p">.</span><span class="n">name</span><span class="p">)</span> <span class="c1">#i am class
</span>
<span class="n">obj</span><span class="p">.</span><span class="n">myName</span><span class="o">=</span><span class="s">'i am obj'</span>
<span class="k">print</span><span class="p">(</span><span class="n">obj</span><span class="p">.</span><span class="n">myName</span><span class="p">)</span> <span class="c1">#i am obj
</span>
<span class="k">def</span> <span class="nf">printName</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
<span class="n">Class</span><span class="p">.</span><span class="n">printName</span><span class="o">=</span><span class="n">printName</span>
<span class="c1">#即使在类动态添加方法之前实例化,还是可以调用之后动态添加的方法
</span><span class="n">obj</span><span class="p">.</span><span class="n">printName</span><span class="p">()</span> <span class="c1">#i am class
</span></code></pre></div></div>
<p>如果想限制实例可以添加的属性,可以在定义类的时候使用<code class="language-plaintext highlighter-rouge">__slots__</code>。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="n">__slots__</span><span class="o">=</span><span class="p">(</span><span class="s">'name'</span><span class="p">,</span><span class="s">'age'</span><span class="p">)</span>
<span class="n">obj</span><span class="o">=</span><span class="n">Class</span><span class="p">();</span>
<span class="n">obj</span><span class="p">.</span><span class="n">name</span><span class="o">=</span><span class="s">'lisong'</span>
<span class="n">obj</span><span class="p">.</span><span class="n">age</span><span class="o">=</span><span class="mi">18</span>
<span class="k">print</span><span class="p">(</span><span class="n">obj</span><span class="p">.</span><span class="n">name</span><span class="p">,</span><span class="n">obj</span><span class="p">.</span><span class="n">name</span><span class="p">)</span> <span class="c1">#lisong 18
</span>
<span class="n">obj</span><span class="p">.</span><span class="n">title</span><span class="o">=</span><span class="s">'title'</span> <span class="c1">#报错
#__slots__只能限制实例的动态添加属性和方法,类依然能够动态添加
</span><span class="n">Class</span><span class="p">.</span><span class="n">title</span><span class="o">=</span><span class="s">'class title'</span>
<span class="k">print</span><span class="p">(</span><span class="n">obj</span><span class="p">.</span><span class="n">title</span><span class="p">)</span> <span class="c1">#class title
</span></code></pre></div></div>
<h3 id="property">@property</h3>
<p>@property修饰器可以把类的一个方法变成属性,这样就可以拦截取值操作了,同时这个修饰器还会创造一个以方法名称为后缀的setter修饰器,使用这个修改可以拦截取值操作。@property类似于js中的defineProperty。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'return:'</span><span class="o">+</span><span class="bp">self</span><span class="p">.</span><span class="n">_name</span><span class="p">)</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">_name</span>
<span class="o">@</span><span class="n">name</span><span class="p">.</span><span class="n">setter</span>
<span class="k">def</span> <span class="nf">name</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">name</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'set:'</span><span class="o">+</span><span class="n">name</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_name</span><span class="o">=</span><span class="n">name</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">age</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">18</span>
<span class="n">obj</span><span class="o">=</span><span class="n">Class</span><span class="p">();</span>
<span class="n">obj</span><span class="p">.</span><span class="n">name</span><span class="o">=</span><span class="s">'lisong'</span> <span class="c1">#set:lisong
</span>
<span class="n">obj</span><span class="p">.</span><span class="n">name</span> <span class="c1">#return:lisong
</span>
<span class="n">obj</span><span class="p">.</span><span class="n">age</span><span class="o">=</span><span class="mi">20</span> <span class="c1">#报错,没有定义setter,只能读取,不能设置
</span>
<span class="k">print</span><span class="p">(</span><span class="n">obj</span><span class="p">.</span><span class="n">age</span><span class="p">)</span> <span class="c1">#18
</span></code></pre></div></div>
<h3 id="多重继承">多重继承</h3>
<p>python天生支持多重继承,而静态语言java只支持单继承。</p>
<p>在类的设计中,如果想让某一个类既有A类的功能,又有B类的功能,只需要让这个类同时继承A类和B类就行了,这种设计通常称之为Mixin。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Runnable</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'i can run'</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Flyable</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">fly</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'i can fly'</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">SuperMan</span><span class="p">(</span><span class="n">Runnable</span><span class="p">,</span><span class="n">Flyable</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">man</span><span class="o">=</span><span class="n">SuperMan</span><span class="p">()</span>
<span class="n">man</span><span class="p">.</span><span class="n">run</span><span class="p">()</span> <span class="c1">#i can run
</span>
<span class="n">man</span><span class="p">.</span><span class="n">fly</span><span class="p">()</span> <span class="c1">#i can fly
</span></code></pre></div></div>
<h3 id="定制类">定制类</h3>
<p>在类中重定义形如<code class="language-plaintext highlighter-rouge">__xxx__</code>的方法,可以让类的实例有特殊的行为。</p>
<h4 id="len"><strong>len</strong></h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">10</span>
<span class="nb">len</span><span class="p">(</span><span class="n">Class</span><span class="p">())</span> <span class="c1">#10
</span></code></pre></div></div>
<h4 id="str"><strong>str</strong></h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s">'i am class'</span>
<span class="c1">#默认__str__()打印出内存地址,可以重定义
</span><span class="k">print</span><span class="p">(</span><span class="n">Class</span><span class="p">())</span> <span class="c1">#i am class
</span></code></pre></div></div>
<h4 id="iter"><strong>iter</strong></h4>
<p>如果一个类想被用于for … in循环,类似list或tuple那样,就必须实现一个<code class="language-plaintext highlighter-rouge">__iter__()</code>方法,该方法返回一个迭代对象,然后,Python的for循环就会不断调用该迭代对象的<code class="language-plaintext highlighter-rouge">__next__()</code>方法拿到循环的下一个值,直到遇到<code class="language-plaintext highlighter-rouge">StopIteration</code>错误时退出循环。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">Class</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="c1">#1 2 3
</span>
<span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="nb">sum</span><span class="o">=</span><span class="mi">0</span>
<span class="k">def</span> <span class="nf">__iter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span>
<span class="k">def</span> <span class="nf">__next__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="nb">sum</span><span class="o">+=</span><span class="mi">1</span>
<span class="k">if</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="nb">sum</span><span class="o">></span><span class="mi">3</span><span class="p">):</span>
<span class="k">raise</span> <span class="nb">StopIteration</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="nb">sum</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">Class</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="c1">#1 2 3
</span></code></pre></div></div>
<h4 id="getitem"><strong>getitem</strong></h4>
<p>使实例可以作用于下标操作符。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="n">arr</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="nb">int</span><span class="p">)):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">arr</span><span class="p">[</span><span class="n">n</span><span class="p">]</span>
<span class="k">if</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">n</span><span class="p">,</span><span class="nb">slice</span><span class="p">)):</span>
<span class="n">start</span><span class="o">=</span><span class="n">n</span><span class="p">.</span><span class="n">start</span>
<span class="n">stop</span><span class="o">=</span><span class="n">n</span><span class="p">.</span><span class="n">stop</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">arr</span><span class="p">[</span><span class="n">start</span><span class="p">:</span><span class="n">stop</span><span class="p">]</span>
<span class="n">obj</span><span class="o">=</span><span class="n">Class</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">obj</span><span class="p">[</span><span class="mi">2</span><span class="p">])</span> <span class="c1">#3
</span><span class="k">print</span><span class="p">(</span><span class="n">obj</span><span class="p">[</span><span class="mi">1</span><span class="p">:</span><span class="mi">3</span><span class="p">])</span> <span class="c1">#2,3
</span></code></pre></div></div>
<h4 id="getattr"><strong>getattr</strong></h4>
<p>当属性或方法不存在时会调用该方法。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__getattr__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">attr</span><span class="p">):</span>
<span class="k">if</span><span class="p">(</span><span class="n">attr</span><span class="o">==</span><span class="s">'name'</span><span class="p">):</span>
<span class="k">return</span> <span class="s">'lisong'</span>
<span class="k">if</span><span class="p">(</span><span class="n">attr</span><span class="o">==</span><span class="s">'age'</span><span class="p">):</span>
<span class="k">return</span> <span class="k">lambda</span><span class="p">:</span><span class="mi">18</span>
<span class="n">obj</span><span class="o">=</span><span class="n">Class</span><span class="p">()</span>
<span class="n">obj</span><span class="p">.</span><span class="n">name</span> <span class="c1">#lisong
</span><span class="n">obj</span><span class="p">.</span><span class="n">age</span><span class="p">()</span> <span class="c1">#18
</span></code></pre></div></div>
<h4 id="call"><strong>call</strong></h4>
<p>如果定义了<code class="language-plaintext highlighter-rouge">__call__</code>方法,实例可以当做方法调用。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Class</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'run __call__'</span><span class="p">)</span>
<span class="n">obj</span><span class="o">=</span><span class="n">Class</span><span class="p">()</span>
<span class="n">obj</span><span class="p">()</span> <span class="c1">#run __call__
</span></code></pre></div></div>
<h3 id="枚举">枚举</h3>
<p>枚举对象自动赋给成员int常量,默认从1开始计数</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span>
<span class="n">Month</span> <span class="o">=</span> <span class="n">Enum</span><span class="p">(</span><span class="s">'Month'</span><span class="p">,</span> <span class="p">(</span><span class="s">'Jan'</span><span class="p">,</span> <span class="s">'Feb'</span><span class="p">,</span> <span class="s">'Mar'</span><span class="p">,</span> <span class="s">'Apr'</span><span class="p">,</span> <span class="s">'May'</span><span class="p">,</span> <span class="s">'Jun'</span><span class="p">,</span> <span class="s">'Jul'</span><span class="p">,</span> <span class="s">'Aug'</span><span class="p">,</span> <span class="s">'Sep'</span><span class="p">,</span> <span class="s">'Oct'</span><span class="p">,</span> <span class="s">'Nov'</span><span class="p">,</span> <span class="s">'Dec'</span><span class="p">))</span>
<span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">member</span> <span class="ow">in</span> <span class="n">Month</span><span class="p">.</span><span class="n">__members__</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="n">member</span><span class="p">,</span> <span class="s">','</span><span class="p">,</span> <span class="n">member</span><span class="p">.</span><span class="n">value</span><span class="p">)</span>
<span class="c1">#Jan => Month.Jan , 1
#Feb => Month.Feb , 2
#Mar => Month.Mar , 3
#Apr => Month.Apr , 4
#May => Month.May , 5
#Jun => Month.Jun , 6
#Jul => Month.Jul , 7
#Aug => Month.Aug , 8
#Sep => Month.Sep , 9
#Oct => Month.Oct , 10
#Nov => Month.Nov , 11
#Dec => Month.Dec , 12
</span></code></pre></div></div>
<p>通过继承Enum,可以自定义枚举成员的值</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">enum</span> <span class="kn">import</span> <span class="n">Enum</span><span class="p">,</span> <span class="n">unique</span>
<span class="o">@</span><span class="n">unique</span>
<span class="k">class</span> <span class="nc">Weekday</span><span class="p">(</span><span class="n">Enum</span><span class="p">):</span>
<span class="n">Sun</span> <span class="o">=</span> <span class="mi">0</span> <span class="c1"># Sun的value被设定为0
</span> <span class="n">Mon</span> <span class="o">=</span> <span class="mi">1</span>
<span class="n">Tue</span> <span class="o">=</span> <span class="mi">2</span>
<span class="n">Wed</span> <span class="o">=</span> <span class="mi">3</span>
<span class="n">Thu</span> <span class="o">=</span> <span class="mi">4</span>
<span class="n">Fri</span> <span class="o">=</span> <span class="mi">5</span>
<span class="n">Sat</span> <span class="o">=</span> <span class="mi">6</span>
<span class="k">print</span><span class="p">(</span><span class="n">Weekday</span><span class="p">.</span><span class="n">Mon</span><span class="p">)</span> <span class="c1">#1
</span><span class="n">Weekday</span><span class="p">.</span><span class="n">Mon</span><span class="o">=</span><span class="mi">10</span> <span class="c1">#报错,不可以重新赋值
</span><span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">member</span> <span class="ow">in</span> <span class="n">Weekday</span><span class="p">.</span><span class="n">__members__</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="s">'=>'</span><span class="p">,</span> <span class="n">member</span><span class="p">,</span> <span class="s">','</span><span class="p">,</span> <span class="n">member</span><span class="p">.</span><span class="n">value</span><span class="p">)</span>
<span class="c1">#Sun => Weekday.Sun , 0
#Mon => Weekday.Mon , 1
#Tue => Weekday.Tue , 2
#Wed => Weekday.Wed , 3
#Thu => Weekday.Thu , 4
#Fri => Weekday.Fri , 5
#Sat => Weekday.Sat , 6
</span></code></pre></div></div>
<h3 id="动态创建类">动态创建类</h3>
<h4 id="type方法">type方法</h4>
<p>type动态创建类需要三个参数</p>
<ul>
<li>class的名称;</li>
<li>继承的父类集合,注意Python支持多重继承,如果只有一个父类,别忘了tuple的单元素写法;</li>
<li>class的方法名称与函数绑定,这里我们把函数fn绑定到方法名hello上。</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">hello</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'hello world'</span><span class="p">)</span>
<span class="n">Hello</span><span class="o">=</span><span class="nb">type</span><span class="p">(</span><span class="s">'Hello'</span><span class="p">,(</span><span class="nb">object</span><span class="p">,),{</span><span class="s">'hello'</span><span class="p">:</span><span class="n">hello</span><span class="p">})</span>
<span class="n">Hello</span><span class="p">().</span><span class="n">hello</span><span class="p">()</span> <span class="c1">#hello world
</span></code></pre></div></div>
<h4 id="metaclass">metaclass</h4>
<p>metaclass允许你创建类或者修改类。换句话说,你可以把类看成是metaclass创建出来的“实例”。</p>
<p>当定义一个类的时候,传递一个metaclass关键字参数,则定义了当创建该类的时候需要使用该关键字所指向的类的<code class="language-plaintext highlighter-rouge">__new__</code>方法来创建。</p>
<p><code class="language-plaintext highlighter-rouge">__new__()</code>方法接收到的参数依次是:</p>
<ul>
<li>当前准备创建的类;</li>
<li>类的名字;</li>
<li>类继承的父类集合;</li>
<li>类的方法、属性集合。</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">superMetaclass</span><span class="p">(</span><span class="nb">type</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__new__</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span><span class="n">name</span><span class="p">,</span><span class="n">bases</span><span class="p">,</span><span class="n">attrs</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="n">obj</span><span class="p">)</span> <span class="c1">#<class '__main__.superMetaclass'>
</span> <span class="n">attrs</span><span class="p">[</span><span class="s">'test'</span><span class="p">]</span> <span class="o">=</span> <span class="k">lambda</span> <span class="bp">self</span><span class="p">:</span><span class="s">'this is a test'</span>
<span class="k">return</span> <span class="nb">type</span><span class="p">.</span><span class="n">__new__</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span><span class="n">name</span><span class="p">,</span><span class="n">bases</span><span class="p">,</span><span class="n">attrs</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Class</span><span class="p">(</span><span class="n">metaclass</span><span class="o">=</span><span class="n">superMetaclass</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'running'</span><span class="p">)</span>
<span class="n">obj</span><span class="o">=</span><span class="n">Class</span><span class="p">()</span>
<span class="n">obj</span><span class="p">.</span><span class="n">test</span><span class="p">()</span> <span class="c1">#this is a test
</span><span class="n">obj</span><span class="p">.</span><span class="n">run</span><span class="p">()</span> <span class="c1">#running
</span></code></pre></div></div>
python(面向对象)
2018-05-09T00:00:00+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/05/09/python(面向对象)
<h3 id="类和实例">类和实例</h3>
<p>python类语法和java有点类似,<code class="language-plaintext highlighter-rouge">__init__</code>作为自动初始化方法,第一个self参数代表了java中的this,创建对象的时候不需要new关键字。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">Student</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">name</span><span class="p">,</span><span class="n">age</span><span class="p">):</span>
<span class="p">...</span> <span class="bp">self</span><span class="p">.</span><span class="n">name</span><span class="o">=</span><span class="n">name</span>
<span class="p">...</span> <span class="bp">self</span><span class="p">.</span><span class="n">age</span><span class="o">=</span><span class="n">age</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">stu</span><span class="o">=</span><span class="n">Student</span><span class="p">(</span><span class="s">'lisong'</span><span class="p">,</span><span class="mi">18</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">stu</span><span class="p">.</span><span class="n">name</span>
<span class="s">'lisong'</span>
<span class="o">>>></span> <span class="n">sut</span><span class="p">.</span><span class="n">age</span>
<span class="mi">18</span>
</code></pre></div></div>
<h3 id="访问限制">访问限制</h3>
<p>在python中,以双下划线<code class="language-plaintext highlighter-rouge">__</code>开头的变量属于私有变量,外部访问不了,变量名类似<code class="language-plaintext highlighter-rouge">__xxx__</code>的,也就是以双下划线开头,并且以双下划线结尾的,是特殊变量,特殊变量是可以直接访问的,不是<code class="language-plaintext highlighter-rouge">private</code>变量,所以,不能用<code class="language-plaintext highlighter-rouge">__name__</code>、<code class="language-plaintext highlighter-rouge">__score__</code>这样的变量名。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">Student</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">name</span><span class="p">,</span><span class="n">age</span><span class="p">):</span>
<span class="p">...</span> <span class="bp">self</span><span class="p">.</span><span class="n">__name</span><span class="o">=</span><span class="n">name</span>
<span class="p">...</span> <span class="bp">self</span><span class="p">.</span><span class="n">__age</span><span class="o">=</span><span class="n">age</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">stu</span><span class="o">=</span><span class="n">Student</span><span class="p">(</span><span class="s">'lisong'</span><span class="p">,</span><span class="mi">18</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">stu</span><span class="p">.</span><span class="n">__name</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="nb">AttributeError</span><span class="p">:</span> <span class="s">'Student'</span> <span class="nb">object</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="s">'__name'</span>
<span class="o">>>></span>
</code></pre></div></div>
<p>虽然看起来,私有变量在外部访问不了,但其实这是个假象,python解释器只是把这些双下划线开头的私有变量改了标识,比如<code class="language-plaintext highlighter-rouge">__name</code>被改成了<code class="language-plaintext highlighter-rouge">_Student__name</code>。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">stu</span><span class="p">.</span><span class="n">_Student__name</span>
<span class="s">'lisong'</span>
<span class="o">>>></span>
</code></pre></div></div>
<p>虽然这样我们就可以访问到私有变量了,但强烈建议不要这么写代码,因为不同的python解释器可能会按不同的规则来改写私有变量。</p>
<h3 id="继承和多态">继承和多态</h3>
<h4 id="继承">继承</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">Animal</span><span class="p">:</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c1">#self不能省略
</span><span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="s">'animal is running'</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="k">class</span> <span class="nc">Dog</span><span class="p">(</span><span class="n">Animal</span><span class="p">):</span>
<span class="p">...</span> <span class="k">pass</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="k">class</span> <span class="nc">Cat</span><span class="p">(</span><span class="n">Animal</span><span class="p">):</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">run</span><span class="p">():</span> <span class="c1">#可覆盖父类方法
</span><span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="s">'cat is running'</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">ani</span><span class="o">=</span><span class="n">Animal</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">ani</span><span class="p">.</span><span class="n">run</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">ani</span><span class="o">=</span><span class="n">Animal</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">ani</span><span class="p">.</span><span class="n">run</span><span class="p">()</span>
<span class="n">animal</span> <span class="ow">is</span> <span class="n">running</span>
<span class="o">>>></span> <span class="n">dog</span><span class="o">=</span><span class="n">Dog</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">dog</span><span class="p">.</span><span class="n">run</span><span class="p">()</span>
<span class="n">animal</span> <span class="ow">is</span> <span class="n">running</span>
<span class="o">>>></span> <span class="n">cat</span><span class="o">=</span><span class="n">Cat</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">cat</span><span class="p">.</span><span class="n">run</span><span class="p">()</span>
<span class="n">cat</span> <span class="ow">is</span> <span class="n">running</span>
</code></pre></div></div>
<h4 id="多态">多态</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">Animal</span><span class="p">:</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="s">'animal is running'</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="k">class</span> <span class="nc">Dog</span><span class="p">(</span><span class="n">Animal</span><span class="p">):</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="s">'dog is running'</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="k">class</span> <span class="nc">Cat</span><span class="p">(</span><span class="n">Animal</span><span class="p">):</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="s">'cat is running'</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="k">def</span> <span class="nf">run_twice</span><span class="p">(</span><span class="n">animal</span><span class="p">):</span>
<span class="p">...</span> <span class="n">animal</span><span class="p">.</span><span class="n">run</span><span class="p">()</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">run_twice</span><span class="p">(</span><span class="n">Animal</span><span class="p">())</span>
<span class="n">animal</span> <span class="ow">is</span> <span class="n">running</span>
<span class="o">>>></span>
<span class="o">>>></span> <span class="n">run_twice</span><span class="p">(</span><span class="n">Dog</span><span class="p">())</span>
<span class="n">dog</span> <span class="ow">is</span> <span class="n">running</span>
<span class="o">>>></span>
<span class="o">>>></span> <span class="n">run_twice</span><span class="p">(</span><span class="n">Cat</span><span class="p">())</span>
<span class="n">cat</span> <span class="ow">is</span> <span class="n">running</span>
<span class="o">>>></span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">Animal</span><span class="p">(),</span><span class="n">Animal</span><span class="p">)</span>
<span class="bp">True</span>
<span class="o">>>></span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">Dog</span><span class="p">(),</span><span class="n">Animal</span><span class="p">)</span>
<span class="bp">True</span>
<span class="o">>>></span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">Dog</span><span class="p">(),</span><span class="n">Dog</span><span class="p">)</span>
<span class="bp">True</span>
<span class="o">>>></span>
</code></pre></div></div>
<p>python中的多态与java的多态是有一些区别的,java属于静态语言,定义run_twice时,会去检查其参数类型,不是Animal时会编译(编译成字节码)不通过,而对于python来说,参数类型可以任何类型,运行时才知道具体的类型,只要类型有run方法就能正确运行,这里的特性和js类似。</p>
<p>多态的意义在于,我们可以定义一种操作,这种操作需要某一种类型的数据就能正确执行,而不需要管数据具体的类型时哪一种类型,只要其父类是操作需要的类型就行了。</p>
<h3 id="类型判断">类型判断</h3>
<p>python类型判断有两个方法,一个type方法,一个是isinstance方法,type返回一个类型,isinstance接受两个参数,两个函数的功能基本一样,不过isinstance还可以判断继承类。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Animal</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'animal is running'</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Dog</span><span class="p">(</span><span class="n">Animal</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'animal is running'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="mi">123</span><span class="p">)</span><span class="o">==</span><span class="nb">int</span><span class="p">)</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="s">'abc'</span><span class="p">)</span><span class="o">==</span><span class="nb">str</span><span class="p">)</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="bp">True</span><span class="p">)</span><span class="o">==</span><span class="nb">bool</span><span class="p">)</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">Dog</span><span class="p">())</span><span class="o">==</span><span class="n">Dog</span><span class="p">)</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">Dog</span><span class="p">())</span><span class="o">==</span><span class="n">Animal</span><span class="p">)</span> <span class="c1">#False
</span>
<span class="k">print</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="mi">123</span><span class="p">,</span><span class="nb">int</span><span class="p">))</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="s">'abc'</span><span class="p">,</span><span class="nb">str</span><span class="p">))</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="bp">True</span><span class="p">,</span><span class="nb">bool</span><span class="p">))</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">Dog</span><span class="p">(),</span><span class="n">Dog</span><span class="p">))</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">Dog</span><span class="p">(),</span><span class="n">Animal</span><span class="p">))</span> <span class="c1">#True
</span>
<span class="k">def</span> <span class="nf">fn</span><span class="p">():</span>
<span class="k">pass</span>
<span class="kn">import</span> <span class="nn">types</span> <span class="c1">#如果要判断是否为函数,需要引入types
</span>
<span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">fn</span><span class="p">)</span><span class="o">==</span><span class="n">types</span><span class="p">.</span><span class="n">FunctionType</span><span class="p">)</span> <span class="c1">#True
</span><span class="k">print</span><span class="p">(</span><span class="nb">isinstance</span><span class="p">(</span><span class="n">fn</span><span class="p">,</span><span class="n">types</span><span class="p">.</span><span class="n">FunctionType</span><span class="p">))</span> <span class="c1">#True
</span></code></pre></div></div>
<h3 id="静态属性">静态属性</h3>
<p>可以给类添加静态属性,通过对象和类都可以访问静态属性</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Animal</span><span class="p">:</span>
<span class="n">name</span><span class="o">=</span><span class="s">'kitty'</span>
<span class="k">print</span><span class="p">(</span><span class="n">Animal</span><span class="p">.</span><span class="n">name</span><span class="p">)</span> <span class="c1">#kitty
</span><span class="k">print</span><span class="p">(</span><span class="n">Animal</span><span class="p">().</span><span class="n">name</span><span class="p">)</span> <span class="c1">#kitty
</span></code></pre></div></div>
python(模块)
2018-05-08T00:00:00+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/05/08/python(模块)
<h2 id="模块">模块</h2>
<p>在python中,一个.py文件就是一个模块,引入一个模块后,就可以用这么模块名调用其里面的所有声明的方法和变量。</p>
<h3 id="模块的结构">模块的结构</h3>
<p>python的模块结构类似java,不过要把一个目录声明为包目录,需要在目录下放置一个<code class="language-plaintext highlighter-rouge">__init__.py</code>文件,这个文件也代表这个目录的默认模块,也可以不放<code class="language-plaintext highlighter-rouge">__init__.py</code>,不过这样就不能直接引用该目录的默认包了。</p>
<p><strong>例如:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/python/python(模块)-1.png" alt="" /></p>
<p>可以这么引用:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">import</span> <span class="nn">pack</span>
<span class="o">>>></span> <span class="n">pack</span><span class="p">.</span><span class="n">test</span><span class="p">()</span>
<span class="n">pack</span>
<span class="o">>>></span> <span class="kn">from</span> <span class="nn">pack</span> <span class="kn">import</span> <span class="n">test</span> <span class="c1">#可以只引用某一个方法或变量
</span><span class="o">>>></span> <span class="n">test</span><span class="p">()</span>
<span class="n">pack</span>
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">pack.mod</span>
<span class="o">>>></span> <span class="n">pack</span><span class="p">.</span><span class="n">mod</span><span class="p">.</span><span class="n">test</span><span class="p">()</span>
<span class="n">pack</span><span class="p">.</span><span class="n">mod</span>
<span class="o">>>></span> <span class="n">pm</span> <span class="o">=</span> <span class="n">pack</span><span class="p">.</span><span class="n">mod</span> <span class="c1">#可以将长模块付给变量
</span><span class="o">>>></span> <span class="n">pm</span><span class="p">.</span><span class="n">test</span><span class="p">()</span>
<span class="n">pack</span><span class="p">.</span><span class="n">mod</span>
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">pack.pack1</span>
<span class="o">>>></span> <span class="n">pack</span><span class="p">.</span><span class="n">pack1</span><span class="p">.</span><span class="n">test</span><span class="p">()</span>
<span class="n">pack</span><span class="p">.</span><span class="n">pack1</span>
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">pack.pack1.mod</span>
<span class="o">>>></span> <span class="n">pack</span><span class="p">.</span><span class="n">pack1</span><span class="p">.</span><span class="n">mod</span><span class="p">.</span><span class="n">test</span><span class="p">()</span>
<span class="n">pack</span><span class="p">.</span><span class="n">pack1</span><span class="p">.</span><span class="n">mod</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="作用域">作用域</h3>
<p>类似<code class="language-plaintext highlighter-rouge">__xxx__</code>这样的变量是特殊变量,可以被直接引用,但是有特殊用途,比如<code class="language-plaintext highlighter-rouge">__author__</code>,<code class="language-plaintext highlighter-rouge">__name__</code>就是特殊变量,我们自己的变量一般不要用这种变量名。</p>
<p>类似<code class="language-plaintext highlighter-rouge">_xxx</code>和<code class="language-plaintext highlighter-rouge">__xxx</code>这样的函数或变量就是非公开的(private),不应该被直接引用,比如<code class="language-plaintext highlighter-rouge">_abc</code>,<code class="language-plaintext highlighter-rouge">__abc</code>等。
之所以我们说,private函数和变量“不应该”被直接引用,而不是“不能”被直接引用,是因为Python并没有一种方法可以完全限制访问private函数或变量,但是,从编程习惯上不应该引用private函数或变量。</p>
<p>标准模块示例:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python3
# -*- coding: utf-8 -*-
</span>
<span class="s">' a test module '</span>
<span class="c1">#使用__author__变量把作者写进去,这样当你公开源代码后别人就可以瞻仰你的大名
</span><span class="n">__author__</span> <span class="o">=</span> <span class="s">'Michael Liao'</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="k">def</span> <span class="nf">test</span><span class="p">():</span>
<span class="n">args</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span><span class="o">==</span><span class="mi">1</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Hello, world!'</span><span class="p">)</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">args</span><span class="p">)</span><span class="o">==</span><span class="mi">2</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Hello, %s!'</span> <span class="o">%</span> <span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Too many arguments!'</span><span class="p">)</span>
<span class="c1">#当我们在命令行运行hello模块文件时,Python解释器把一个特殊变量__name__置为__main__,
#而如果在其他地方导入该hello模块时,if判断将失败
</span><span class="k">if</span> <span class="n">__name__</span><span class="o">==</span><span class="s">'__main__'</span><span class="p">:</span>
<span class="n">test</span><span class="p">()</span>
</code></pre></div></div>
Oauth2.0
2018-05-06T23:55:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2018/05/06/OAuth2.0
<h2 id="oauth20">Oauth2.0</h2>
<p>OAuth的作用就是让”客户端”安全可控地获取”用户”的授权,与”服务商提供商”进行互动。它在”客户端”与”服务提供商”之间,设置了一个授权层(authorization layer)。”客户端”不能直接登录”服务提供商”,只能登录授权层,以此将用户与客户端区分开来</p>
<h3 id="名词解释">名词解释</h3>
<ul>
<li>Third-party application:第三方应用,本文中指客户端。</li>
<li>HTTP service:服务提供商。</li>
<li>Resource Owner:资源所有者,即用户。</li>
<li>User Agent:用户代理,本文中就是指浏览器。</li>
<li>Authorization server:认证服务器,即服务提供商专门用来处理认证的服务器。</li>
<li>Resource server:资源服务器,即服务提供商存放用户生成的资源的服务器。它与认证服务器,可以是同一台服务器,也可以是不同的服务器。</li>
</ul>
<h3 id="运行流程">运行流程</h3>
<p><img src="https://wanls4583.github.io/images/posts/其他/oauth-0.png" alt="" /></p>
<ul>
<li>A:用户打开客户端以后,客户端要求用户给予授权。</li>
<li>B:用户同意给予客户端授权。</li>
<li>C:客户端使用上一步获得的授权,向认证服务器申请令牌。</li>
<li>D:认证服务器对客户端进行认证以后,确认无误,同意发放令牌。</li>
<li>E:客户端使用令牌,向资源服务器申请获取资源。</li>
<li>F:资源服务器确认令牌无误,同意向客户端开放资源。</li>
</ul>
<h3 id="授权模式">授权模式</h3>
<ul>
<li>授权码模式</li>
<li>简化模式</li>
<li>密码模式</li>
<li>客户端模式</li>
</ul>
<h3 id="授权码模式">授权码模式</h3>
<p>授权码模式是功能最完整、流程最严密的授权模式。具体流程如下:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/oauth-1.png" alt="" /></p>
<ul>
<li>A:用户访问客户端,客户端使用重定向将用户导向授权页面(这个页面由认证服务器提供),请求中带有客户端提供的重定向URI(用于C步骤中认证服务器重定向);</li>
<li>B:用户选择是否授权;</li>
<li>C:如果用户授权,则认证服务器将用户导向客户端提供的重定向URI,并且带上授权码(Authoriztion Code);</li>
<li>D:用户代理将授权码发送给客户端,客户端在后台将授权码和重定向URI(与A步骤中的重定向URI一致,需要验证链接)发送给认证服务器换取access token(访问令牌)和refresh token(更新令牌);</li>
<li>E:如果认证服务器验证通过,则发送access token和refresh token给客户端,随后客户端就可以使用该token去访问资源服务器相应的资源了。</li>
</ul>
<h4 id="各步骤中的主要请求返回参数如下">各步骤中的主要请求/返回参数如下:</h4>
<p><strong>A:客户端请求授权</strong></p>
<ul>
<li>response_type:表示授权类型,必选项,此处的值固定为”code”。</li>
<li>client_id:表示客户端的ID,必选项。</li>
<li>redirect_uri:表示重定向URI,可选项。</li>
<li>scope:表示申请的权限范围,可选项。</li>
<li>state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。</li>
</ul>
<p><strong>C:认证服务器返回授权码</strong></p>
<ul>
<li>code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。<strong>该码与客户端ID和重定向URI,是一一对应关系</strong>。</li>
<li>state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。</li>
</ul>
<p><strong>D:客户端请求令牌</strong></p>
<ul>
<li>grant_type:表示使用的授权模式,必选项,此处的值固定为”authorization_code”。</li>
<li>code:表示上一步获得的授权码,必选项。</li>
<li>redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。</li>
<li>client_id:表示客户端ID,必选项。</li>
</ul>
<p><strong>E:认证服务器返回令牌</strong></p>
<ul>
<li>access_token:表示访问令牌,必选项。</li>
<li>token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。</li>
<li>expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。</li>
<li>refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。</li>
<li>scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。</li>
</ul>
<h3 id="简化模式">简化模式</h3>
<p>简化模式(implicit grant type)不通过第三方应用程序的服务器,直接在浏览器中向认证服务器申请令牌,跳过了”授权码”这个步骤,因此得名。所有步骤在浏览器中完成,令牌对访问者是可见的,且客户端不需要认证。</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/oauth-2.png" alt="" /></p>
<ul>
<li>A:客户端将用户导向认证服务器。</li>
<li>B:用户决定是否给于客户端授权。</li>
<li>C:假设用户给予授权,认证服务器将用户导向客户端指定的”重定向URI”,并在URI的Hash部分包含访问令牌。</li>
<li>D:浏览器向资源服务器发出请求,其中不包括上一步收到的Hash值(Hash值还在地址栏里)。</li>
<li>E:资源服务器返回一个网页,其中包含的代码可以获取Hash值中的令牌。</li>
<li>F:浏览器执行上一步获得的脚本,解析地址栏上的Hash,提取出令牌(可以认为只有资源服务器返回的代码能解析出token)。
-G:浏览器将令牌发给客户端。</li>
</ul>
<h4 id="各步骤中的主要请求返回参数如下-1">各步骤中的主要请求/返回参数如下:</h4>
<p><strong>A:客户端请求授权</strong></p>
<ul>
<li>response_type:表示授权类型,此处的值固定为”token”(授权码模式这里为code),必选项。</li>
<li>client_id:表示客户端的ID,必选项。</li>
<li>redirect_uri:表示重定向的URI,可选项。</li>
<li>scope:表示权限范围,可选项。</li>
<li>state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。</li>
</ul>
<p><strong>C:服务器返回token</strong></p>
<ul>
<li>access_token:表示访问令牌,必选项。</li>
<li>token_type:表示令牌类型,该值大小写不敏感,必选项。</li>
<li>expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。</li>
<li>scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。</li>
<li>state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。</li>
</ul>
<p>需要注意,与授权码模式不同,这里没有refresh_token。</p>
<div class="language-http highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err"> </span><span class="k">HTTP</span><span class="o">/</span><span class="m">1.1</span> <span class="m">302</span> <span class="ne">Found</span>
<span class="s"> Location: http://example.com/cb#access_token=2YotnFZFEjr1zCsicMWpAA</span>
<span class="s"> &state=xyz&token_type=example&expires_in=3600</span>
</code></pre></div></div>
<h3 id="密码模式">密码模式</h3>
<p>密码模式(Resource Owner Password Credentials Grant)中,用户向客户端提供自己的用户名和密码。客户端使用这些信息,向”服务商提供商”索要授权。</p>
<p>在这种模式中,用户必须把自己的密码给客户端,但是客户端不得储存密码。这通常用在用户对客户端高度信任的情况下,比如客户端是操作系统的一部分,或者由一个著名公司出品。而认证服务器只有在其他授权模式无法执行的情况下,才能考虑使用这种模式。</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/oauth-2.png" alt="" /></p>
<ul>
<li>A:用户向客户端提供用户名和密码。</li>
<li>B:客户端将用户名和密码发给认证服务器,向后者请求令牌。</li>
<li>C:认证服务器确认无误后,向客户端提供访问令牌。</li>
</ul>
<h4 id="各步骤中的主要请求返回参数如下-2">各步骤中的主要请求/返回参数如下:</h4>
<p><strong>B:客户端请求令牌</strong></p>
<ul>
<li>grant_type:表示授权类型,此处的值固定为”password”,必选项。</li>
<li>username:表示用户名,必选项。</li>
<li>password:表示用户的密码,必选项。</li>
<li>scope:表示权限范围,可选项。</li>
</ul>
<p><strong>C:服务器返回token(与授权码模式一致)</strong></p>
<h3 id="客户端模式">客户端模式</h3>
<p>客户端模式(Client Credentials Grant)指客户端以自己的名义,而不是以用户的名义,向”服务提供商”进行认证。严格地说,客户端模式并不属于OAuth框架所要解决的问题。在这种模式中,用户直接向客户端注册,客户端以自己的名义要求”服务提供商”提供服务,其实不存在授权问题。</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/oauth-2.png" alt="" /></p>
<p>-A:客户端向认证服务器进行身份认证,并要求一个访问令牌。
-B:认证服务器确认无误后,向客户端提供访问令牌。</p>
<h4 id="各步骤中的主要请求返回参数如下-3">各步骤中的主要请求/返回参数如下:</h4>
<p><strong>A:客户端请求令牌</strong></p>
<ul>
<li>granttype:表示授权类型,此处的值固定为”clientcredentials”,必选项。</li>
<li>scope:表示权限范围,可选项。</li>
</ul>
<p><strong>B:服务器返回token(与简化模式一致)</strong></p>
<p><strong>参考链接</strong></p>
<ul>
<li><a href="http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html">http://www.ruanyifeng.com/blog/2014/05/oauth_2_0.html</a></li>
</ul>
python(函数式编程)
2018-05-06T00:00:00+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/05/06/python(函数式编程)
<h2 id="函数式编程">函数式编程</h2>
<p>函数式编程就是一种抽象程度很高的编程范式,纯粹的函数式编程语言编写的函数没有变量,因此,任意一个函数,只要输入是确定的,输出就是确定的,这种纯函数我们称之为没有副作用。</p>
<p>函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数。Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。</p>
<h3 id="高阶函数">高阶函数</h3>
<p>如果一个函数就可以接收另一个函数作为参数,这种函数就称之为高阶函数。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">f</span><span class="p">):</span>
<span class="k">return</span> <span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">+</span> <span class="n">f</span><span class="p">(</span><span class="n">y</span><span class="p">)</span>
</code></pre></div></div>
<h4 id="map函数"><code class="language-plaintext highlighter-rouge">map()</code>函数</h4>
<p><code class="language-plaintext highlighter-rouge">map()</code>函数接收两个参数,一个是函数,一个是<code class="language-plaintext highlighter-rouge">Iterable</code>对象,<code class="language-plaintext highlighter-rouge">map</code>将传入的函数依次作用到序列的每个元素,并把结果作为新的<code class="language-plaintext highlighter-rouge">Iterator</code>对象返回。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="p">...</span> <span class="k">return</span> <span class="n">x</span><span class="o">*</span><span class="n">x</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">g</span><span class="o">=</span><span class="nb">map</span><span class="p">(</span><span class="n">f</span><span class="p">,[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="nb">list</span><span class="p">(</span><span class="n">g</span><span class="p">)</span> <span class="c1">#list与iter相反,可以把Iterator变成Iterable,如果该g无限大,将会内存溢出
</span><span class="p">[</span><span class="mi">4</span><span class="p">,</span> <span class="mi">9</span><span class="p">]</span>
<span class="o">>>></span>
</code></pre></div></div>
<h4 id="reduce函数"><code class="language-plaintext highlighter-rouge">reduce()</code>函数</h4>
<p><code class="language-plaintext highlighter-rouge">reduce</code>把一个函数作用在一个<code class="language-plaintext highlighter-rouge">Iterable</code>对象上,这个函数必须接收两个参数,<code class="language-plaintext highlighter-rouge">reduce</code>把结果继续和序列的下一个元素做累积计算,其效果就是:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">reduce</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="p">[</span><span class="n">x1</span><span class="p">,</span> <span class="n">x2</span><span class="p">,</span> <span class="n">x3</span><span class="p">,</span> <span class="n">x4</span><span class="p">])</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">f</span><span class="p">(</span><span class="n">x1</span><span class="p">,</span> <span class="n">x2</span><span class="p">),</span> <span class="n">x3</span><span class="p">),</span> <span class="n">x4</span><span class="p">)</span><span class="err">`</span>
</code></pre></div></div>
<p>序列求和:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">):</span>
<span class="p">...</span> <span class="k">return</span> <span class="n">x</span><span class="o">+</span><span class="n">y</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="kn">from</span> <span class="nn">functools</span> <span class="kn">import</span> <span class="nb">reduce</span>
<span class="o">>>></span> <span class="nb">reduce</span><span class="p">(</span><span class="n">f</span><span class="p">,[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span> <span class="c1">#如果第二个参数是一个Iterator并且无穷大,将会内存溢出
</span><span class="mi">6</span>
<span class="o">>>></span>
</code></pre></div></div>
<h4 id="filter函数"><code class="language-plaintext highlighter-rouge">filter()</code>函数</h4>
<p>类似js数组的filter函数,用于过滤序列,其返回的时一个Iterator对象。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">g</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="p">...</span> <span class="k">while</span><span class="p">(</span><span class="n">n</span><span class="o">></span><span class="mi">0</span><span class="p">):</span>
<span class="p">...</span> <span class="k">yield</span> <span class="n">n</span>
<span class="p">...</span> <span class="n">n</span><span class="o">=</span><span class="n">n</span><span class="o">-</span><span class="mi">1</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="k">def</span> <span class="nf">is_odd</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="p">...</span> <span class="k">return</span> <span class="n">x</span><span class="o">%</span><span class="mi">2</span><span class="o">==</span><span class="mi">1</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="nb">list</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="n">is_odd</span><span class="p">,</span><span class="n">g</span><span class="p">(</span><span class="mi">10</span><span class="p">)))</span>
<span class="p">[</span><span class="mi">9</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="o">>>></span> <span class="nb">list</span><span class="p">(</span><span class="nb">filter</span><span class="p">(</span><span class="n">is_odd</span><span class="p">,[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]))</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">]</span>
<span class="o">>>></span>
</code></pre></div></div>
<h4 id="sorted函数"><code class="language-plaintext highlighter-rouge">sorted()</code>函数</h4>
<p>用于排序,第二个关键字参数key可以接受一个函数作为排序依据,第三个关键字reverse参数是个<code class="language-plaintext highlighter-rouge">Boolean</code>值,可以改变排序顺序。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="nb">sorted</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="o">>>></span> <span class="nb">sorted</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">],</span><span class="n">key</span><span class="o">=</span><span class="nb">abs</span><span class="p">)</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">]</span>
<span class="o">>>></span> <span class="nb">sorted</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">],</span><span class="n">key</span><span class="o">=</span><span class="nb">abs</span><span class="p">,</span> <span class="n">reverse</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="p">[</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="o">>>></span> <span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="c1">#自定义函数只接收一个参数
</span><span class="p">...</span> <span class="k">if</span><span class="p">(</span><span class="n">x</span><span class="o"><</span><span class="mi">0</span><span class="p">):</span>
<span class="p">...</span> <span class="k">return</span> <span class="o">-</span><span class="n">x</span>
<span class="p">...</span> <span class="k">else</span><span class="p">:</span>
<span class="p">...</span> <span class="k">return</span> <span class="n">x</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="nb">sorted</span><span class="p">([</span><span class="mi">2</span><span class="p">,</span><span class="o">-</span><span class="mi">3</span><span class="p">,</span><span class="mi">1</span><span class="p">],</span><span class="n">key</span><span class="o">=</span><span class="n">f</span><span class="p">)</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="o">-</span><span class="mi">3</span><span class="p">]</span>
<span class="o">>>></span>
</code></pre></div></div>
jenkins+github自动化构建的简单流程
2018-05-05T00:00:00+00:00
https://blog.lisong.hn.cn/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/2018/05/05/jenkins+github自动化构建的简单流程
<h2 id="jenkins">jenkins</h2>
<p>jenkins是一个基于java的自动化构建工具,使用它可以为我们解决很多重复的工作,其官网提供了很多插件,根据不同的需求选择相应的插件,可以很大的提高我们的开发或者部署的效率。</p>
<p>本篇文章主要介绍如何实现使用git提交代码到github时,怎么触发Jenkins的自动构建任务。</p>
<h3 id="一安装jenkins">一、安装jenkins</h3>
<h4 id="下载jenkinswar项目">下载jenkins.war项目</h4>
<p>jenkins的安装很简单,只要下载官网的<a href="http://mirrors.shu.edu.cn/jenkins/war/2.119/jenkins.war">jenkins.war</a>包就行。因为Jenkins是基于java的,所以你首先得安装java的jdk并且配置好环境遍历。做好以上两个步骤,只需在命令行中输入以下命令就可以启动jenkins了:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>java <span class="nt">-jar</span> jenkins.war
</code></pre></div></div>
<p>第一次启动可能有点慢,直达看到<code class="language-plaintext highlighter-rouge">fully up and running </code>才算启动完成,在这之前访问,浏览器控制台可能报错,默认访问地址是<code class="language-plaintext highlighter-rouge">localhost:8080</code>。</p>
<p>启动后,命令行会提示一个初始化密码,打开浏览器访问时需要这个密码去初始化jenkins。</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-1.jpg" alt="" /></p>
<h4 id="配置工作目录">配置工作目录</h4>
<p>初始化完成后,我们可以自己配置一下Jenkins的工作目录,也就是拉取代码存储的目录,这个配置config.xml在Jenkins.war解压后的目录,在命令行里可以看到,找到config.xml,在里面重新配置workspaceDir:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-0.png" alt="" /></p>
<h3 id="二安装github插件并进行配置">二、安装github插件并进行配置</h3>
<h4 id="插件安装">插件安装</h4>
<p>在插件管理中切换到可选插件tab页,输入github过滤,在下方的列表中选择<code class="language-plaintext highlighter-rouge">github</code>插件并进行安装:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-2.jpg" alt="" /></p>
<p>安装好后回到首页点击新建任务:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-3.jpg" alt="" /></p>
<h4 id="源码路径">源码路径</h4>
<p>点击刚新建的项目,配置源码管理,这里配置成github的地址,这样每次构建时都会pull一次远程的代码到本地,然后再进行构建。认证只需点击add,添加自己的github名称和密码就行了:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-4.png" alt="" /></p>
<h4 id="使用触发器">使用触发器</h4>
<p>想要监听git的push操作,需要配置构建触发器,这个触发器可以让github有更新时触发Jenkins的构建任务:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-5.jpg" alt="" /></p>
<h4 id="构建任务">构建任务</h4>
<p>接下来时配置具体的构建任务,我这里是用<code class="language-plaintext highlighter-rouge">git diff --name-only HEAD~ HEAD</code>命令在控制台输出变化的文件,然后进行模块安装和项目编译<code class="language-plaintext highlighter-rouge">cnpm install && npm run build</code>(只能输入两行,多个命令可以用&&连接),Windows batch command构建任务可以输入任何在命令行中的命令,执行命令时的目录就是我们配置的工作目录(代码存放的地方)。</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-6.png" alt="" /></p>
<h4 id="生成github-token">生成github token</h4>
<p>为了让github有更新时,能够及时发送HTTP请求给Jenkins,需要在全局配置里配置github server,这个配置主要用来进行github与Jenkins的通信验证,验证是基于token的,所以我们需要先在github上生成一个token,打开<a href="https://github.com/settings/tokens">token配置链接</a> 添加一个就行了,需要注意的是,token的配置中需要添加admin:org权限。</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-7.jpg" alt="" /></p>
<h4 id="配置连接github-server">配置连接github server</h4>
<p>生成好token后就可以配置Jenkins的github server配置了。</p>
<p>首先在Credentials管理中添加一个Credentials,secret就是刚刚生成的token:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-8.jpg" alt="" /></p>
<p>随后打开全局配置,添加id为test的Credentials:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-9.jpg" alt="" /></p>
<h4 id="配置github-webhook">配置github webhook</h4>
<p>最后需要在github上配置一个webhook钩子,将其地址配置成我们Jenkins服务器的地址,因为我的Jenkins服务器在本地,所以使用了花生壳动态域名,将其映射到内外的8080端口,这样github更新时才能发送post请求通知到Jenkins。</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-10.jpg" alt="" /></p>
<p>将动态域名地址配置到github:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-11.png" alt="" /></p>
<p>secret就是之前添加的token。</p>
<h4 id="测试">测试</h4>
<p>做完这些就可以开始测试了,我们使用git添加一个test.txt空文件push到github,这时就可以在Jenkins任务面板里看到有个任务正在构建:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-12.png" alt="" /></p>
<p>构建完成后,点击进去,选择控制台信息,可以查看到构建的详细信息:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-13.png" alt="" /></p>
<p>命令行的工作目录就是Jenkins拉取下来的源码存储的目录:</p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/jenkins-14.png" alt="" /></p>
python(高级特性)
2018-05-04T00:00:00+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/05/04/python(高级特性)
<h3 id="切片">切片</h3>
<p>类似于js中的slice函数,可以针对数组和字符串进行截取。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">arr</span><span class="o">=</span><span class="p">[</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">2</span><span class="p">]</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">arr</span><span class="p">[:</span><span class="mi">2</span><span class="p">]</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="o">-</span><span class="mi">2</span><span class="p">]</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">arr</span><span class="p">[</span><span class="mi">0</span><span class="p">:]</span>
<span class="p">[</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">]</span>
<span class="o">>>></span> <span class="s">'abcd'</span><span class="p">[</span><span class="mi">0</span><span class="p">:</span><span class="mi">2</span><span class="p">]</span>
<span class="s">'ab'</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="迭代">迭代</h3>
<p>python中迭代只有for..in,数组,字符串,dic,set都可以通过for…in来进行迭代。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]:</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="p">...</span>
<span class="mi">1</span>
<span class="mi">2</span>
<span class="mi">3</span>
<span class="o">>>></span> <span class="k">for</span> <span class="n">ch</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]:</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">ch</span><span class="p">)</span>
<span class="p">...</span>
<span class="mi">1</span>
<span class="mi">2</span>
<span class="mi">3</span>
<span class="o">>>></span> <span class="k">for</span> <span class="n">value</span> <span class="ow">in</span> <span class="p">{</span><span class="s">'a'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span><span class="s">'b'</span><span class="p">:</span><span class="mi">2</span><span class="p">}.</span><span class="n">values</span><span class="p">():</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="p">...</span>
<span class="mi">1</span>
<span class="mi">2</span>
<span class="o">>>></span> <span class="k">for</span> <span class="n">key</span><span class="p">,</span><span class="n">value</span> <span class="ow">in</span> <span class="p">{</span><span class="s">'a'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span><span class="s">'b'</span><span class="p">:</span><span class="mi">2</span><span class="p">}.</span><span class="n">items</span><span class="p">():</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">key</span><span class="p">,</span><span class="n">value</span><span class="p">)</span>
<span class="p">...</span>
<span class="n">a</span> <span class="mi">1</span>
<span class="n">b</span> <span class="mi">2</span>
<span class="o">>>></span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span> <span class="ow">in</span> <span class="p">[(</span><span class="mi">1</span><span class="p">,</span><span class="s">'a'</span><span class="p">),(</span><span class="mi">2</span><span class="p">,</span><span class="s">'b'</span><span class="p">),[</span><span class="mi">3</span><span class="p">,</span><span class="s">'c'</span><span class="p">]]:</span><span class="c1">#每个数组元素的个数都要为两个,多了或少了都不行
</span><span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">)</span>
<span class="p">...</span>
<span class="mi">1</span> <span class="n">a</span>
<span class="mi">2</span> <span class="n">b</span>
<span class="mi">3</span> <span class="n">c</span>
<span class="o">>>></span>
</code></pre></div></div>
<p>可以用isinstance判断对象是否可迭代。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Iterable</span>
<span class="o">>>></span> <span class="nb">isinstance</span><span class="p">(</span><span class="s">'abc'</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">)</span> <span class="c1"># str是否可迭代
</span><span class="bp">True</span>
<span class="o">>>></span> <span class="nb">isinstance</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span> <span class="n">Iterable</span><span class="p">)</span> <span class="c1"># list是否可迭代
</span><span class="bp">True</span>
<span class="o">>>></span> <span class="nb">isinstance</span><span class="p">(</span><span class="mi">123</span><span class="p">,</span> <span class="n">Iterable</span><span class="p">)</span> <span class="c1"># 整数是否可迭代
</span><span class="bp">False</span>
</code></pre></div></div>
<h3 id="列表生成式">列表生成式</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="p">[</span><span class="n">x</span><span class="o">*</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]]</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">9</span><span class="p">]</span>
<span class="o">>>></span> <span class="p">[</span><span class="n">x</span><span class="o">*</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">11</span><span class="p">)]</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">16</span><span class="p">,</span> <span class="mi">25</span><span class="p">,</span> <span class="mi">36</span><span class="p">,</span> <span class="mi">49</span><span class="p">,</span> <span class="mi">64</span><span class="p">,</span> <span class="mi">81</span><span class="p">,</span> <span class="mi">100</span><span class="p">]</span>
<span class="o">>>></span> <span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="n">y</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="s">'abc'</span> <span class="k">for</span> <span class="n">y</span> <span class="ow">in</span> <span class="s">'ABC'</span><span class="p">]</span> <span class="c1">#可以有多个循环
</span><span class="p">[</span><span class="s">'aA'</span><span class="p">,</span> <span class="s">'aB'</span><span class="p">,</span> <span class="s">'aC'</span><span class="p">,</span> <span class="s">'bA'</span><span class="p">,</span> <span class="s">'bB'</span><span class="p">,</span> <span class="s">'bC'</span><span class="p">,</span> <span class="s">'cA'</span><span class="p">,</span> <span class="s">'cB'</span><span class="p">,</span> <span class="s">'cC'</span><span class="p">]</span>
<span class="o">>>></span> <span class="p">[</span><span class="n">x</span><span class="o">+</span><span class="n">y</span> <span class="k">for</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span> <span class="ow">in</span> <span class="p">{</span><span class="s">'a'</span><span class="p">:</span><span class="s">'A'</span><span class="p">,</span><span class="s">'b'</span><span class="p">:</span><span class="s">'B'</span><span class="p">}.</span><span class="n">items</span><span class="p">()]</span>
<span class="p">[</span><span class="s">'aA'</span><span class="p">,</span> <span class="s">'bB'</span><span class="p">]</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="生成器generator">生成器(generator)</h3>
<p>生成器和列表生产式类似,只不过列表生成式最终保存的时列表,而生成器只是保存了算法,生成器中的每个元素都是通过计算获得的。</p>
<h4 id="普通生成器">普通生成器</h4>
<p>语法类似列表生成式,只不过[]换成(),可以不断通过next获取下一个值,最后将抛出StopIteration错误,也可以使用for循环来迭代。不管使用next还是for循环,都只能遍历一次。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">g</span><span class="o">=</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="mi">4</span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="mi">9</span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="nb">StopIteration</span>
<span class="o">>>></span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">g</span><span class="p">:</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span>
<span class="o">>>></span> <span class="n">g</span><span class="o">=</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="o">>>></span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">g</span><span class="p">:</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="p">...</span>
<span class="mi">1</span>
<span class="mi">4</span>
<span class="mi">9</span>
</code></pre></div></div>
<h4 id="函数生成器">函数生成器</h4>
<p>当一个函数里含有yield关键字时,这个函数就变成了一个生成器。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">fab</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="p">...</span> <span class="n">t</span><span class="p">,</span><span class="n">a</span><span class="p">,</span><span class="n">b</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="mi">1</span>
<span class="p">...</span> <span class="k">while</span><span class="p">(</span><span class="n">t</span><span class="o"><</span><span class="n">n</span><span class="p">):</span>
<span class="p">...</span> <span class="k">yield</span> <span class="n">b</span>
<span class="p">...</span> <span class="n">a</span><span class="p">,</span><span class="n">b</span><span class="p">,</span><span class="n">t</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span><span class="n">a</span><span class="o">+</span><span class="n">b</span><span class="p">,</span><span class="n">t</span><span class="o">+</span><span class="mi">1</span>
<span class="p">...</span> <span class="k">return</span> <span class="s">'done'</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="n">fab</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="p">...</span>
<span class="mi">1</span>
<span class="mi">1</span>
<span class="mi">2</span>
<span class="mi">3</span>
<span class="mi">5</span>
<span class="o">>>></span> <span class="n">g</span> <span class="o">=</span> <span class="n">fab</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="o">>>></span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="p">...</span> <span class="k">try</span><span class="p">:</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">))</span>
<span class="p">...</span> <span class="k">except</span> <span class="nb">StopIteration</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span> <span class="c1">#函数返回值将挂载到StopIteration错误对象上
</span><span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">value</span><span class="p">)</span>
<span class="p">...</span> <span class="k">break</span>
<span class="p">...</span>
<span class="mi">1</span>
<span class="mi">1</span>
<span class="mi">2</span>
<span class="mi">3</span>
<span class="mi">5</span>
<span class="n">done</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="迭代器">迭代器</h3>
<p>list,tuple,str,set,dec,generator都可以被for循环所迭代,因此它们都属于Iterable(可迭代对象)。不过generator比较特殊,它不但属于可迭代对象,同时还属于Iterator(迭代器),python中规定可以被next()函数调用并不断返回下一个值的对象称为迭代器:Iterator。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Iterator</span>
<span class="o">>>></span> <span class="kn">from</span> <span class="nn">collections</span> <span class="kn">import</span> <span class="n">Iterable</span>
<span class="o">>>></span> <span class="nb">isinstance</span><span class="p">((</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)),</span> <span class="n">Iterator</span><span class="p">)</span>
<span class="bp">True</span>
<span class="o">>>></span> <span class="nb">isinstance</span><span class="p">((</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">)),</span> <span class="n">Iterable</span><span class="p">)</span>
<span class="bp">True</span>
<span class="o">>>></span>
</code></pre></div></div>
<p>可以通过iter方法将Iterable对象变成Iterator对象</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">g</span> <span class="o">=</span> <span class="p">[</span><span class="n">x</span><span class="o">*</span><span class="n">x</span> <span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]]</span>
<span class="o">>>></span> <span class="n">g</span> <span class="o">=</span> <span class="nb">iter</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="mi">4</span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">g</span><span class="p">)</span>
<span class="mi">9</span>
<span class="o">>>></span>
</code></pre></div></div>
<p>Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并不断返回下一个数据,直到没有数据时抛出StopIteration错误。可以把这个数据流看做是一个有序序列,但我们却不能提前知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时它才会计算。</p>
<p>Iterator甚至可以表示一个无限大的数据流,例如全体自然数。而使用list是永远不可能存储全体自然数的。Python的for循环本质上就是通过不断调用next()函数实现的。</p>
python(函数)
2018-05-03T00:00:00+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/05/03/python(函数)
<h3 id="常用内置函数">常用内置函数</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="nb">abs</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
<span class="mi">100</span>
<span class="o">>>></span> <span class="nb">abs</span><span class="p">(</span><span class="o">-</span><span class="mi">20</span><span class="p">)</span>
<span class="mi">20</span>
<span class="o">>>></span> <span class="nb">abs</span><span class="p">(</span><span class="mf">12.34</span><span class="p">)</span>
<span class="mf">12.34</span>
<span class="o">>>></span> <span class="nb">max</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="mi">2</span>
<span class="o">>>></span> <span class="nb">max</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="o">-</span><span class="mi">5</span><span class="p">)</span>
<span class="mi">3</span>
<span class="o">>>></span> <span class="nb">int</span><span class="p">(</span><span class="s">'123'</span><span class="p">)</span>
<span class="mi">123</span>
<span class="o">>>></span> <span class="nb">int</span><span class="p">(</span><span class="mf">12.34</span><span class="p">)</span>
<span class="mi">12</span>
<span class="o">>>></span> <span class="nb">float</span><span class="p">(</span><span class="s">'12.34'</span><span class="p">)</span>
<span class="mf">12.34</span>
<span class="o">>>></span> <span class="nb">str</span><span class="p">(</span><span class="mf">1.23</span><span class="p">)</span>
<span class="s">'1.23'</span>
<span class="o">>>></span> <span class="nb">str</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
<span class="s">'100'</span>
<span class="o">>>></span> <span class="nb">bool</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="bp">True</span>
<span class="o">>>></span> <span class="nb">bool</span><span class="p">(</span><span class="s">''</span><span class="p">)</span>
<span class="bp">False</span>
<span class="o">>>></span> <span class="nb">hex</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
<span class="s">'0x64'</span>
</code></pre></div></div>
<h3 id="定义函数">定义函数</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">my_abs</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="p">(</span><span class="nb">int</span><span class="p">,</span> <span class="nb">float</span><span class="p">)):</span>
<span class="k">raise</span> <span class="nb">TypeError</span><span class="p">(</span><span class="s">'bad operand type'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">x</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">return</span> <span class="n">x</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="o">-</span><span class="n">x</span>
</code></pre></div></div>
<h3 id="pass">pass</h3>
<p>pass可以用来定义空函数</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fn</span><span class="p">():</span>
<span class="k">pass</span>
</code></pre></div></div>
<p>也可以用来当做占位符</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="n">x</span><span class="o">></span><span class="mi">1</span><span class="p">):</span>
<span class="k">pass</span>
</code></pre></div></div>
<h3 id="导入math库">导入math库</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">math</span>
<span class="k">def</span> <span class="nf">move</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">step</span><span class="p">,</span> <span class="n">angle</span><span class="o">=</span><span class="mi">0</span><span class="p">):</span>
<span class="n">nx</span> <span class="o">=</span> <span class="n">x</span> <span class="o">+</span> <span class="n">step</span> <span class="o">*</span> <span class="n">math</span><span class="p">.</span><span class="n">cos</span><span class="p">(</span><span class="n">angle</span><span class="p">)</span>
<span class="n">ny</span> <span class="o">=</span> <span class="n">y</span> <span class="o">-</span> <span class="n">step</span> <span class="o">*</span> <span class="n">math</span><span class="p">.</span><span class="n">sin</span><span class="p">(</span><span class="n">angle</span><span class="p">)</span>
<span class="k">return</span> <span class="n">nx</span><span class="p">,</span> <span class="n">ny</span>
</code></pre></div></div>
<h3 id="默认参数">默认参数</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">power</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="mi">2</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="n">n</span><span class="p">)</span>
</code></pre></div></div>
<p>当默认参数是引用时,如果每次调用都使用默认参数,则默认参数引用时不变的</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">a</span><span class="o">=</span><span class="p">[]):</span>
<span class="p">...</span> <span class="n">a</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="p">...</span> <span class="k">return</span> <span class="n">a</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">test</span><span class="p">()</span>
<span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">test</span><span class="p">()</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">test</span><span class="p">()</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">1</span><span class="p">]</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="可变参数">可变参数</h3>
<p>可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuplex</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">calc</span><span class="p">(</span><span class="o">*</span><span class="n">numbers</span><span class="p">):</span>
<span class="p">...</span> <span class="nb">sum</span> <span class="o">=</span> <span class="mi">0</span>
<span class="p">...</span> <span class="k">for</span> <span class="n">n</span> <span class="ow">in</span> <span class="n">numbers</span><span class="p">:</span>
<span class="p">...</span> <span class="nb">sum</span> <span class="o">=</span> <span class="nb">sum</span> <span class="o">+</span> <span class="n">n</span> <span class="o">*</span> <span class="n">n</span>
<span class="p">...</span> <span class="k">return</span> <span class="nb">sum</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">calc</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
<span class="mi">14</span>
<span class="o">>>></span>
</code></pre></div></div>
<p>可以在一个数组前加一个*号将数组变成可变参数</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">nums</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">calc</span><span class="p">(</span><span class="o">*</span><span class="n">nums</span><span class="p">)</span>
<span class="mi">14</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="关键字参数">关键字参数</h3>
<p>关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">person</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">age</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="s">'name:'</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="s">'age:'</span><span class="p">,</span> <span class="n">age</span><span class="p">,</span> <span class="s">'other:'</span><span class="p">,</span> <span class="n">kw</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">person</span><span class="p">(</span><span class="s">'lisong'</span><span class="p">,</span><span class="s">'18'</span><span class="p">,</span><span class="n">sex</span><span class="o">=</span><span class="s">'man'</span><span class="p">,</span><span class="n">city</span><span class="o">=</span><span class="s">'hunan'</span><span class="p">)</span>
<span class="n">name</span><span class="p">:</span> <span class="n">lisong</span> <span class="n">age</span><span class="p">:</span> <span class="mi">18</span> <span class="n">other</span><span class="p">:</span> <span class="p">{</span><span class="s">'sex'</span><span class="p">:</span> <span class="s">'man'</span><span class="p">,</span> <span class="s">'city'</span><span class="p">:</span> <span class="s">'hunan'</span><span class="p">}</span>
<span class="o">>>></span>
</code></pre></div></div>
<p>和可变参数类似,也可以先组装出一个dict,然后,用**把该dict转换为关键字参数传进去</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">other</span><span class="o">=</span><span class="p">{</span><span class="s">'sex'</span><span class="p">:</span><span class="s">'man'</span><span class="p">,</span><span class="s">'city'</span><span class="p">:</span><span class="s">'hunan'</span><span class="p">}</span>
<span class="o">>>></span> <span class="n">person</span><span class="p">(</span><span class="s">'lisong'</span><span class="p">,</span><span class="s">'18'</span><span class="p">,</span><span class="o">**</span><span class="n">other</span><span class="p">)</span>
<span class="n">name</span><span class="p">:</span> <span class="n">lisong</span> <span class="n">age</span><span class="p">:</span> <span class="mi">18</span> <span class="n">other</span><span class="p">:</span> <span class="p">{</span><span class="s">'sex'</span><span class="p">:</span> <span class="s">'man'</span><span class="p">,</span> <span class="s">'city'</span><span class="p">:</span> <span class="s">'hunan'</span><span class="p">}</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="命名关键字参数">命名关键字参数</h3>
<p>命名关键字参数用来限制关键字参数的名字,需要使用一个*号来分割,代表后面的参数为命名关键字参数</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">person</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">age</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">city</span><span class="p">,</span> <span class="n">sex</span><span class="p">):</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">name</span><span class="p">,</span><span class="n">age</span><span class="p">,</span><span class="n">city</span><span class="p">,</span><span class="n">sex</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">person</span><span class="p">(</span><span class="s">'lisong'</span><span class="p">,</span><span class="mi">18</span><span class="p">,</span><span class="n">sex</span><span class="o">=</span><span class="s">'man'</span><span class="p">,</span><span class="n">city</span><span class="o">=</span><span class="s">'hunan'</span><span class="p">)</span>
<span class="n">lisong</span> <span class="mi">18</span> <span class="n">hunan</span> <span class="n">man</span>
</code></pre></div></div>
<p>此时仍然可以使用**把dict转换为关键字参数传进去</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">other</span><span class="o">=</span><span class="p">{</span><span class="s">'sex'</span><span class="p">:</span><span class="s">'man'</span><span class="p">,</span><span class="s">'city'</span><span class="p">:</span><span class="s">'hunan'</span><span class="p">}</span>
<span class="o">>>></span> <span class="n">person</span><span class="p">(</span><span class="s">'lisong'</span><span class="p">,</span><span class="mi">18</span><span class="p">,</span><span class="o">**</span><span class="n">other</span><span class="p">)</span>
<span class="n">lisong</span> <span class="mi">18</span> <span class="n">hunan</span> <span class="n">man</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="参数的组合">参数的组合</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">f1</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="o">*</span><span class="n">args</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="s">'a ='</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="s">'b ='</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="s">'c ='</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="s">'args ='</span><span class="p">,</span> <span class="n">args</span><span class="p">,</span> <span class="s">'kw ='</span><span class="p">,</span> <span class="n">kw</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">f1</span><span class="p">(</span><span class="s">'a'</span><span class="p">,</span><span class="s">'b'</span><span class="p">,</span><span class="s">'c'</span><span class="p">,</span><span class="n">d</span><span class="o">=</span><span class="s">'d'</span><span class="p">,</span><span class="n">e</span><span class="o">=</span><span class="s">'e'</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span> <span class="n">c</span> <span class="o">=</span> <span class="n">c</span> <span class="n">args</span> <span class="o">=</span> <span class="p">()</span> <span class="n">kw</span> <span class="o">=</span> <span class="p">{</span><span class="s">'d'</span><span class="p">:</span> <span class="s">'d'</span><span class="p">,</span> <span class="s">'e'</span><span class="p">:</span> <span class="s">'e'</span><span class="p">}</span>
<span class="o">>>></span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">def</span> <span class="nf">f2</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="o">*</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="s">'a ='</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="s">'b ='</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="s">'c ='</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="s">'d ='</span><span class="p">,</span> <span class="n">d</span><span class="p">,</span> <span class="s">'kw ='</span><span class="p">,</span> <span class="n">kw</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">f2</span><span class="p">(</span><span class="s">'a'</span><span class="p">,</span><span class="s">'b'</span><span class="p">,</span><span class="n">d</span><span class="o">=</span><span class="s">'d'</span><span class="p">,</span><span class="n">e</span><span class="o">=</span><span class="s">'e'</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span> <span class="n">c</span> <span class="o">=</span> <span class="mi">0</span> <span class="n">d</span> <span class="o">=</span> <span class="n">d</span> <span class="n">kw</span> <span class="o">=</span> <span class="p">{</span><span class="s">'e'</span><span class="p">:</span> <span class="s">'e'</span><span class="p">}</span>
<span class="o">>>></span>
</code></pre></div></div>
<h3 id="递归函数">递归函数</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fact</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">n</span><span class="o">==</span><span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">n</span> <span class="o">*</span> <span class="n">fact</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span>
</code></pre></div></div>
<p>如果n太大,很容易造成堆栈溢出。其实所有的递归函数都可以写成循环的方式,但循环的逻辑不如递归清晰。解决递归调用栈溢出的方法是通过<strong>尾递归</strong>优化,事实上尾递归和循环的效果是一样的,所以,把循环看成是一种特殊的尾递归函数也是可以的。</p>
<p>上面的<code class="language-plaintext highlighter-rouge">fact(n)</code>函数由于<code class="language-plaintext highlighter-rouge">return n \* fact(n - 1)</code>引入了乘法表达式,所以就不是尾递归了。要改成尾递归方式,需要多一点代码,主要是要把每一步的乘积传入到递归函数中:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fact</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">return</span> <span class="n">fact_iter</span><span class="p">(</span><span class="n">n</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">fact_iter</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">product</span><span class="p">):</span>
<span class="k">if</span> <span class="n">num</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">product</span>
<span class="k">return</span> <span class="n">fact_iter</span><span class="p">(</span><span class="n">num</span> <span class="o">-</span> <span class="mi">1</span><span class="p">,</span> <span class="n">num</span> <span class="o">*</span> <span class="n">product</span><span class="p">)</span>
</code></pre></div></div>
<p>可以看到,<code class="language-plaintext highlighter-rouge">return fact_iter(num - 1, num * product)</code>仅返回递归函数本身,<code class="language-plaintext highlighter-rouge">num - 1和num \* product</code>在函数调用前就会被计算,不影响函数调用。</p>
<p><code class="language-plaintext highlighter-rouge">fact(5)</code>对应的<code class="language-plaintext highlighter-rouge">fact_iter(5, 1)</code>的调用如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">===></span> <span class="n">fact_iter</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="o">===></span> <span class="n">fact_iter</span><span class="p">(</span><span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
<span class="o">===></span> <span class="n">fact_iter</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
<span class="o">===></span> <span class="n">fact_iter</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">60</span><span class="p">)</span>
<span class="o">===></span> <span class="n">fact_iter</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">120</span><span class="p">)</span>
<span class="o">===></span> <span class="mi">120</span>
</code></pre></div></div>
<p>尾递归调用时,如果做了优化,栈不会增长,因此,无论多少次调用也不会导致栈溢出。遗憾的是,大多数编程语言没有针对尾递归做优化,Python解释器也没有做优化,所以,即使把上面的fact(n)函数改成尾递归方式,也会导致栈溢出。</p>
Webpack之tapable@0详解
2018-05-02T00:00:00+00:00
https://blog.lisong.hn.cn/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/2018/05/02/webpack之tapable@0详解
<h2 id="插件">插件</h2>
<p>webpack4.0之前的插件是一个具有apply方法的对象,webpack在初始化的时候,会调用所有插件的apply方法。插件的apply方法里一般会通过webpack暴露的compileer和complication对象的plugin方法来进行事件的注册,compileer和complication对象都继承于Tapable。关于webpack4.0之前的插件的开发demo<a href="http://lisong.online/2017/11/webpack-e5-8a-a0-e8-bd-bd-e5-99-a8-e4-b8-8e-e6-8f-92-e4-bb-b6-e5-bc-80-e5-8f-91-e7-ae-80-e5-8d-95-e6-a1-88-e4-be-8b/">请点这里</a></p>
<h2 id="tapable">Tapable</h2>
<p>tapable是webpack的事件流核心库,类似于nodejs的EventEmitter,其中webpack4.0之前的版本都是使用Tapable@0版本,从webpack4.0开始使用Tapable@1版本,本篇文章针对的是Tapable@0,所使用的具体版本为Tapable@0.2.8。Tapable使用plugin(类似EventEmitter.on)方法来注册事件,使用applyPlugin*(类似EventEmitter.emit)来触发事件。</p>
<h3 id="获取tapable">获取Tapable</h3>
<p><a href="https://github.com/webpack/tapable/tree/v0.2.8/lib">Tapable.js</a></p>
<p>下载后修改44行代码使其挂载到window,方便测试</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// module.exports = Tapable;</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">Tapable</span> <span class="o">=</span> <span class="nx">Tapable</span><span class="p">;</span>
</code></pre></div></div>
<h3 id="示例">示例</h3>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>tapable-demo<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"./Tapable.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">tap</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Tapable</span><span class="p">();</span>
<span class="c1">//applyPlugins:依次执行所有插件</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">test1</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">test2</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">applyPlugins</span><span class="p">(</span><span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg2</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">-----------------------</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">//applyPluginsWaterfall:依次执行插件,前一个插件的返回值将作为下一个插件的参数</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testWaterfall</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testWaterfall1</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="c1">//返回值作为下一个插件的第一个返回值</span>
<span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testWaterfall</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testWaterfall2</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">applyPluginsWaterfall</span><span class="p">(</span><span class="dl">'</span><span class="s1">testWaterfall</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg2</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">-----------------------</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">//applyPluginsBailResult(依次执行插件,当插件返回值不为undefined时,停止执行之后的插件)</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testBailResult</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testBailResult1</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="c1">//返回值不为undefined,其后的插件将不再执行</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testBailResult</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testBailResult2</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">applyPluginsBailResult</span><span class="p">(</span><span class="dl">'</span><span class="s1">testBailResult</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg2</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">-----------------------</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">//applyPluginsAsyncSeries:异步的执行插件,后一个插件只有在前一个插件执行回调后才会开始执行,如果有一个插件回调的参数不为false,则将停止执行其后的插件</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeries</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeries1</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="c1">//执行了回调后才会接着执行接下来的插件</span>
<span class="nx">cb</span><span class="p">();</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeries</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeries2</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="c1">//回调参数不为false,将不再继续执行</span>
<span class="nx">cb</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeries</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeries3</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">applyPluginsAsyncSeries</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeries</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg2</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(...</span><span class="nx">arg</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesCb</span><span class="dl">'</span><span class="p">,...</span><span class="nx">arg</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">-----------------------</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">//applyPluginsAsyncSeriesBailResult:和applyPluginsAsyncSeries类似,只是回调停止继续执行的判断条件不同</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesBailResult</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesBailResult1</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="c1">//执行了回调后才会接着执行接下来的插件</span>
<span class="nx">cb</span><span class="p">();</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesBailResult</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesBailResult2</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="c1">//回调参数个数大于0,将不再继续执行</span>
<span class="nx">cb</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesBailResult</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesBailResult3</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">applyPluginsAsyncSeriesBailResult</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesBailResult</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg2</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(...</span><span class="nx">arg</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncSeriesBailResultCb</span><span class="dl">'</span><span class="p">,...</span><span class="nx">arg</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">-----------------------</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">//applyPluginsAsyncWaterfall:和applyPluginsAsyncSeries类似,只不过插件回调参数只能是两个</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncWaterfall</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncWaterfall1</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">);</span>
<span class="c1">//执行了回调后才会接着执行接下来的插件,第一个必须为false,第二值用来传递给下个插件</span>
<span class="nx">cb</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span><span class="dl">'</span><span class="s1">value</span><span class="dl">'</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncWaterfall</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncWaterfall2</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">);</span>
<span class="c1">//回调参数不为false,将不再继续执行</span>
<span class="nx">cb</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncWaterfall</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncWaterfall3</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">applyPluginsAsyncWaterfall</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncWaterfall</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg1</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(...</span><span class="nx">arg</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testAsyncWaterfallCb</span><span class="dl">'</span><span class="p">,...</span><span class="nx">arg</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">-----------------------</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">//applyPluginsParallel:通过for循环并行的执行所有插件,如果某个插件执行了回调且回调参数不为false,则其后所有未执行的插件将不再执行。可能存在插件异步调用了回调,这时候后面的插件可能已经执行了</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallel</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallel1</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallel</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallel2</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="c1">//回调参数不为false,将不再继续执行</span>
<span class="nx">cb</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="c1">//如果换成异步,则后面的插件依然能执行</span>
<span class="c1">// setTimeout(function(){</span>
<span class="c1">// cb(1);</span>
<span class="c1">// },0)</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallel</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallel3</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">applyPluginsParallel</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallel</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg2</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(...</span><span class="nx">arg</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelCb</span><span class="dl">'</span><span class="p">,...</span><span class="nx">arg</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">-----------------------</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">//applyPluginsParallelBailResult:通过for循环执行所有插件,只有第一个插件的回调能执行</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelBailResult</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelBailResult1</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="c1">//回调函数只有第一次执行,并且参数个数要大于0</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">cb</span><span class="p">(</span><span class="kc">null</span><span class="p">,</span><span class="dl">'</span><span class="s1">value</span><span class="dl">'</span><span class="p">);</span>
<span class="p">},</span><span class="mi">100</span><span class="p">)</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelBailResult</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelBailResult2</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="nx">cb</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelBailResult</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelBailResult3</span><span class="dl">'</span><span class="p">,</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">tap</span><span class="p">.</span><span class="nx">applyPluginsParallelBailResult</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelBailResult</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">arg2</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(...</span><span class="nx">arg</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">testParallelBailResultCb</span><span class="dl">'</span><span class="p">,...</span><span class="nx">arg</span><span class="p">);</span>
<span class="p">})</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>运行结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/webpack之tapable@0详解.jpg" alt="" /></p>
vue渲染原理
2018-04-24T00:00:00+00:00
https://blog.lisong.hn.cn/vue/2018/04/24/vue渲染原理
<blockquote>
<p>vue有两种构建方式(独立构建,运行时构建),独立构建包括了编译器部分,运行时构建不包括编译器</p>
</blockquote>
<h3 id="templateelrender的区别">template,el,render的区别</h3>
<p>template,el,render都可以指定具体渲染的内容,当实例参数中同时存在这三个参数时,其优先级为render>template>el,具体参考如下:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>demo<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"vapp-1"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"vapp-2"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"vapp-3"</span><span class="nt">></div></span>
<span class="nt"></body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">.vapp-1</span><span class="dl">'</span><span class="p">,</span> <span class="c1">//此时el只是指定了渲染后的挂载点</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span>
<span class="na">info</span><span class="p">:</span> <span class="dl">'</span><span class="s1">这是通过el属性获取挂载元素的outerHTML方式渲染。</span><span class="dl">'</span>
<span class="p">},</span>
<span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1"><p>这是template属性模板渲染。</p></span><span class="dl">'</span><span class="p">,</span>
<span class="na">render</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">h</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">h</span><span class="p">(</span><span class="dl">'</span><span class="s1">p</span><span class="dl">'</span><span class="p">,</span> <span class="p">{},</span> <span class="dl">'</span><span class="s1">这是render属性方式渲染。</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">.vapp-2</span><span class="dl">'</span><span class="p">,</span> <span class="c1">//此时el只是指定了渲染后的挂载点</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span>
<span class="na">info</span><span class="p">:</span> <span class="dl">'</span><span class="s1">这是通过el属性获取挂载元素的outerHTML方式渲染。</span><span class="dl">'</span>
<span class="p">},</span>
<span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1"><p>这是template属性模板渲染。</p></span><span class="dl">'</span>
<span class="p">})</span>
<span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">.vapp-3</span><span class="dl">'</span><span class="p">,</span> <span class="c1">//此时el.outerHTML为待编译的模板</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span>
<span class="na">info</span><span class="p">:</span> <span class="dl">'</span><span class="s1">这是通过el属性获取挂载元素的outerHTML方式渲染。</span><span class="dl">'</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="nt"></script></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/vue/vue渲染原理-1.jpg" alt="" /></p>
<p>其实这三种编译模式本质都一样,template和el模板都将被编译成render函数,vue渲染是最终都是执行render函数来进行dom的挂载。</p>
<p>如果构建vue实例时没有指定render函数,则必须使用独立构建的vue库文件(vue.js属于独立构建的库文件),如果将上例代码中的vue.js换成vue.runtime.js(运行时库文件),则将报错。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<title>demo</title>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.runtime.js"></script>
</head>
<body>
<div class="vapp-1"></div>
<div class="vapp-2"></div>
<div class="vapp-3"></div>
</body>
<script type="text/javascript">
new Vue({
el: '.vapp-1',
data: {
info: '这是通过el属性获取挂载元素的outerHTML方式渲染。'
},
template: '<p>这是template属性模板渲染。</p>',
render: function(h) {
return h('p', {}, '这是render属性方式渲染。')
}
})
new Vue({
el: '.vapp-2',
data: {
info: '这是通过el属性获取挂载元素的outerHTML方式渲染。'
},
template: '<p>这是template属性模板渲染。</p>'
})
new Vue({
el: '.vapp-3',
data: {
info: '这是通过el属性获取挂载元素的outerHTML方式渲染。'
}
})
</script>
</html>
</code></pre></div></div>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/vue/vue渲染原理-2.jpg" alt="" /></p>
<p>webpack打包vue项目时默认使用的是运行时库,如果需要使用独立构建的库,可以配置别名</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">resolve</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">alias</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">vue$</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">vue/dist/vue.common.js</span><span class="dl">'</span><span class="p">,</span> <span class="c1">//针对CommonJS模式</span>
<span class="c1">//'vue$': 'vue/dist/vue.esm.js', //针对ES Module模式</span>
<span class="c1">//'vue$': 'vue/dist/vue.js', //针对UMD模式</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="render函数">render函数</h3>
<p>render函数没有template里面v-if,v-for等功能,要想实现,需要我们自己手动模拟相关功能。</p>
<h4 id="render模拟v-if">render模拟v-if</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>demo<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app1"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">v-if=</span><span class="s">"level==1"</span><span class="nt">></span>这是level1<span class="nt"></div><div</span> <span class="na">v-if=</span><span class="s">"level==2"</span><span class="nt">></span>这是level2<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app2"</span><span class="nt">></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app1</span><span class="dl">'</span><span class="p">,</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span>
<span class="na">level</span><span class="p">:</span> <span class="mi">1</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span>
<span class="na">level</span><span class="p">:</span> <span class="mi">2</span>
<span class="p">},</span>
<span class="na">render</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">createElement</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">level</span> <span class="o">==</span> <span class="mi">1</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">dom</span> <span class="o">=</span> <span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">,{},</span><span class="dl">'</span><span class="s1">这是level1</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="kd">var</span> <span class="nx">dom</span> <span class="o">=</span> <span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">,{},</span><span class="dl">'</span><span class="s1">这是level2</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">dom</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}).</span><span class="nx">$mount</span><span class="p">(</span><span class="dl">'</span><span class="s1">#app2</span><span class="dl">'</span><span class="p">)</span>
<span class="nt"></script></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/vue/vue渲染原理-3.png" alt="" /></p>
<h4 id="render函数模拟v-model">render函数模拟v-model</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>demo<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
<span class="nt"><my-component</span> <span class="na">ref=</span><span class="s">"input"</span> <span class="err">@</span><span class="na">input=</span><span class="s">"input"</span><span class="nt">></my-component></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">Vue</span><span class="p">.</span><span class="nx">component</span><span class="p">(</span><span class="dl">'</span><span class="s1">my-component</span><span class="dl">'</span><span class="p">,{</span>
<span class="na">data</span><span class="p">:</span> <span class="p">{</span>
<span class="na">value</span><span class="p">:</span> <span class="dl">''</span>
<span class="p">},</span>
<span class="na">render</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">createElement</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nb">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">dom</span> <span class="o">=</span> <span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">input</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="na">domProps</span><span class="p">:</span> <span class="p">{</span>
<span class="na">value</span><span class="p">:</span> <span class="dl">'</span><span class="s1">default</span><span class="dl">'</span><span class="p">,</span>
<span class="p">},</span>
<span class="na">on</span><span class="p">:</span> <span class="p">{</span>
<span class="na">input</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">value</span> <span class="o">=</span> <span class="nx">event</span><span class="p">.</span><span class="nx">target</span><span class="p">.</span><span class="nx">value</span><span class="p">;</span>
<span class="nb">self</span><span class="p">.</span><span class="nx">$emit</span><span class="p">(</span><span class="dl">'</span><span class="s1">input</span><span class="dl">'</span><span class="p">,</span><span class="nb">self</span><span class="p">.</span><span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">dom</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span><span class="p">,</span>
<span class="na">methods</span><span class="p">:</span> <span class="p">{</span>
<span class="na">input</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">value</span><span class="p">,</span><span class="k">this</span><span class="p">.</span><span class="nx">$refs</span><span class="p">.</span><span class="nx">input</span><span class="p">.</span><span class="nx">value</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="nt"></script></span>
<span class="nt"></html></span>
</code></pre></div></div>
<h4 id="render函数之slots">render函数之$slots</h4>
<p>render函数里的$slots只能在组件里使用,vue全局实例里的render函数没有$slots的概念</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>demo<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">src=</span><span class="s">"https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.min.js"</span><span class="nt">></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">id=</span><span class="s">"app"</span><span class="nt">></span>
<span class="nt"><my-component><span></span>lisong<span class="nt"></span></my-component></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">Vue</span><span class="p">.</span><span class="nx">component</span><span class="p">(</span><span class="dl">'</span><span class="s1">my-component</span><span class="dl">'</span><span class="p">,{</span>
<span class="na">render</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">createElement</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nb">self</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">dom</span> <span class="o">=</span> <span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">div</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">hello </span><span class="dl">'</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">$slots</span><span class="p">.</span><span class="k">default</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">children</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="nx">text</span><span class="p">);</span> <span class="c1">//hello lisong</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">$slots</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">dom</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="k">new</span> <span class="nx">Vue</span><span class="p">({</span>
<span class="na">el</span><span class="p">:</span> <span class="dl">'</span><span class="s1">#app</span><span class="dl">'</span>
<span class="p">})</span>
<span class="nt"></script></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/vue/vue渲染原理-4.png" alt="" /></p>
<h4 id="createelement">createElement</h4>
<p>createElement详细参数</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="c1">// 和`v-bind:class`一样的 API</span>
<span class="dl">'</span><span class="s1">class</span><span class="dl">'</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">foo</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="nx">bar</span><span class="p">:</span> <span class="kc">false</span>
<span class="p">},</span>
<span class="c1">// 和`v-bind:style`一样的 API</span>
<span class="nx">style</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="dl">'</span><span class="s1">red</span><span class="dl">'</span><span class="p">,</span>
<span class="nx">fontSize</span><span class="p">:</span> <span class="dl">'</span><span class="s1">14px</span><span class="dl">'</span>
<span class="p">},</span>
<span class="c1">// 正常的 HTML 特性</span>
<span class="nx">attrs</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">id</span><span class="p">:</span> <span class="dl">'</span><span class="s1">foo</span><span class="dl">'</span>
<span class="p">},</span>
<span class="c1">// 组件 props</span>
<span class="nx">props</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">myProp</span><span class="p">:</span> <span class="dl">'</span><span class="s1">bar</span><span class="dl">'</span>
<span class="p">},</span>
<span class="c1">// DOM 属性</span>
<span class="nx">domProps</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">innerHTML</span><span class="p">:</span> <span class="dl">'</span><span class="s1">baz</span><span class="dl">'</span>
<span class="p">},</span>
<span class="c1">// 事件监听器基于 `on`</span>
<span class="c1">// 所以不再支持如 `v-on:keyup.enter` 修饰器</span>
<span class="c1">// 需要手动匹配 keyCode。</span>
<span class="nx">on</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">click</span><span class="p">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">clickHandler</span>
<span class="p">},</span>
<span class="c1">// 仅对于组件,用于监听原生事件,而不是组件内部使用</span>
<span class="c1">// `vm.$emit` 触发的事件。</span>
<span class="nx">nativeOn</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">click</span><span class="p">:</span> <span class="k">this</span><span class="p">.</span><span class="nx">nativeClickHandler</span>
<span class="p">},</span>
<span class="c1">// 自定义指令。注意,你无法对 `binding` 中的 `oldValue`</span>
<span class="c1">// 赋值,因为 Vue 已经自动为你进行了同步。</span>
<span class="nx">directives</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">my-custom-directive</span><span class="dl">'</span><span class="p">,</span>
<span class="na">value</span><span class="p">:</span> <span class="dl">'</span><span class="s1">2</span><span class="dl">'</span><span class="p">,</span>
<span class="na">expression</span><span class="p">:</span> <span class="dl">'</span><span class="s1">1 + 1</span><span class="dl">'</span><span class="p">,</span>
<span class="na">arg</span><span class="p">:</span> <span class="dl">'</span><span class="s1">foo</span><span class="dl">'</span><span class="p">,</span>
<span class="na">modifiers</span><span class="p">:</span> <span class="p">{</span>
<span class="na">bar</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="c1">// Scoped slots in the form of</span>
<span class="c1">// { name: props => VNode | Array<VNode> }</span>
<span class="nx">scopedSlots</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">default</span><span class="p">:</span> <span class="nx">props</span> <span class="o">=></span> <span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">span</span><span class="dl">'</span><span class="p">,</span> <span class="nx">props</span><span class="p">.</span><span class="nx">text</span><span class="p">)</span>
<span class="p">},</span>
<span class="c1">// 如果组件是其他组件的子组件,需为插槽指定名称</span>
<span class="nx">slot</span><span class="p">:</span> <span class="dl">'</span><span class="s1">name-of-slot</span><span class="dl">'</span><span class="p">,</span>
<span class="c1">// 其他特殊顶层属性</span>
<span class="nx">key</span><span class="p">:</span> <span class="dl">'</span><span class="s1">myKey</span><span class="dl">'</span><span class="p">,</span>
<span class="nx">ref</span><span class="p">:</span> <span class="dl">'</span><span class="s1">myRef</span><span class="dl">'</span>
<span class="p">}</span>
</code></pre></div></div>
npm包发布
2018-04-20T03:31:58+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2018/04/20/npm包发布
<h2 id="npm包发布流程">npm包发布流程</h2>
<ul>
<li>首先你得有一个 自己的 npmjs.com 的账号,该账号需要邮箱验证(命令行登录时需要填写邮箱)</li>
<li>npm init生成package.json</li>
<li>npm login登录</li>
<li>npm publish发布(包名称不能与npm上已有的包同名)</li>
</ul>
<p>npm在全局变为淘宝的镜像源后,登录和发布包失败
命令修改如下,可以发布到npmjs</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm login --registry http://registry.npmjs.org
npm publish --registry http://registry.npmjs.org
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/其他/2018-04-20-npm包发布-1.jpg" alt="" /></p>
python(list与dic)
2018-04-02T14:04:19+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/04/02/python(list与dic)
<h2 id="dic">dic</h2>
<p>相当于js中的对象</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">a</span><span class="o">=</span><span class="p">{</span><span class="s">'a'</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span><span class="s">'b'</span><span class="p">:</span><span class="mi">2</span><span class="p">}</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">{</span><span class="s">'a'</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s">'b'</span><span class="p">:</span> <span class="mi">2</span><span class="p">}</span>
<span class="o">>>></span> <span class="n">a</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'a'</span><span class="p">)</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="n">a</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'c'</span><span class="p">,</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="c1">#如果不存在则返回定义的数
</span><span class="o">-</span><span class="mi">1</span>
<span class="o">>>></span> <span class="n">a</span><span class="p">[</span><span class="s">'b'</span><span class="p">]</span>
<span class="mi">2</span>
<span class="o">>>></span> <span class="n">a</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="s">'a'</span><span class="p">)</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">{</span><span class="s">'b'</span><span class="p">:</span> <span class="mi">2</span><span class="p">}</span>
</code></pre></div></div>
<h2 id="set">set</h2>
<p>集合,存储不重复的数据,创建时需要传递一个list</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">a</span><span class="o">=</span><span class="nb">set</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">}</span>
<span class="o">>>></span> <span class="n">a</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="mi">4</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">}</span>
<span class="o">>>></span> <span class="n">a</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">}</span>
</code></pre></div></div>
<p>可以使用&,|</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="nb">set</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span><span class="o">&</span><span class="nb">set</span><span class="p">;([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">])</span>
<span class="p">{</span><span class="mi">1</span><span class="p">}</span>
<span class="o">>>></span> <span class="nb">set</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">3</span><span class="p">])</span><span class="o">|</span><span class="nb">set</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">])</span>
<span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">}</span>
</code></pre></div></div>
python(条件与循环)
2018-03-26T14:26:08+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/03/26/python(条件与循环)
<h2 id="if语句">if语句</h2>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">a</span><span class="o">=</span><span class="mi">99</span>
<span class="k">if</span><span class="p">(</span><span class="n">a</span><span class="o">></span><span class="mi">90</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'优秀'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'一般'</span><span class="p">)</span>
<span class="n">a</span><span class="o">=</span><span class="mi">100</span>
<span class="k">if</span><span class="p">(</span><span class="n">a</span><span class="o">></span><span class="mi">99</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'优秀'</span><span class="p">)</span>
<span class="k">elif</span><span class="p">(</span><span class="n">a</span><span class="o">></span><span class="mi">80</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'良'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'一般'</span><span class="p">)</span>
</code></pre></div></div>
<h2 id="循环">循环</h2>
<p>循环有两种:for…in,while</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sum</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">x</span> <span class="ow">in</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">10</span><span class="p">]:</span>
<span class="nb">sum</span> <span class="o">=</span> <span class="nb">sum</span> <span class="o">+</span> <span class="n">x</span>
<span class="k">print</span><span class="p">(</span><span class="nb">sum</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sum</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">while</span><span class="p">(</span><span class="nb">sum</span><span class="o"><</span><span class="mi">100</span><span class="p">):</span>
<span class="nb">sum</span><span class="o">=</span><span class="nb">sum</span><span class="o">+</span><span class="mi">1</span>
<span class="k">print</span><span class="p">(</span><span class="nb">sum</span><span class="p">)</span>
</code></pre></div></div>
python(数组)
2018-03-26T13:51:23+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/03/26/python(数组)
<h2 id="list">list:</h2>
<p>Python内置的一种数据类型是列表:list。list是一种有序的集合,可以随时添加和删除其中的元素。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">a</span><span class="o">=</span><span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</code></pre></div></div>
<p>insert()</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">a</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">4</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">]</span>
</code></pre></div></div>
<p>pop()</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">a</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>
<span class="mi">3</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">a</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="mi">4</span>
<span class="o">>>></span> <span class="n">a</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
</code></pre></div></div>
<p>倒数</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">]</span>
<span class="o">>>></span> <span class="n">a</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="mi">2</span>
</code></pre></div></div>
<h2 id="tuple">tuple</h2>
<p>另一种有序列表叫元组:tuple。tuple和list非常类似,但是tuple一旦初始化就不能修改</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">b</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">b</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span><span class="o">=</span><span class="mi">2</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">""</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span>
<span class="nb">TypeError</span><span class="p">:</span> <span class="s">'tuple'</span> <span class="nb">object</span> <span class="n">does</span> <span class="ow">not</span> <span class="n">support</span> <span class="n">item</span> <span class="n">assignment</span>
</code></pre></div></div>
<p>对于只有一个元素的tuple,为了避免与表达式()冲突,后面需要加一个‘,’:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">b</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,)</span>
<span class="o">>>></span> <span class="n">b</span>
<span class="p">(</span><span class="mi">1</span><span class="p">,)</span>
<span class="o">>>></span> <span class="n">b</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="n">b</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">""</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span>
<span class="nb">IndexError</span><span class="p">:</span> <span class="nb">tuple</span> <span class="n">index</span> <span class="n">out</span> <span class="n">of</span> <span class="nb">range</span>
</code></pre></div></div>
<p>list,tuple可以随意组合</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">t</span> <span class="o">=</span> <span class="p">(</span><span class="s">'a'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">,</span> <span class="p">[</span><span class="s">'A'</span><span class="p">,</span> <span class="s">'B'</span><span class="p">])</span>
<span class="o">>>></span> <span class="n">t</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="s">'X'</span>
<span class="o">>>></span> <span class="n">t</span>
<span class="p">(</span><span class="s">'a'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">,</span> <span class="p">[</span><span class="s">'X'</span><span class="p">,</span> <span class="s">'B'</span><span class="p">])</span>
</code></pre></div></div>
python(字符串和编码)
2018-03-25T15:08:20+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/03/25/python(字符串和编码)
<p>Unicode把所有语言都统一到一套编码里,这样就不会再有乱码问题了。Unicode标准在不断发展,但最常用的是用两个字节表示一个字符(如果要用到非常偏僻的字符,就需要4个字节)。</p>
<p>本着节约的精神,又出现了把Unicode编码转化为“可变长编码”的UTF-8编码。UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。</p>
<p>UTF-8编码有一个额外的好处,就是ASCII编码实际上可以被看成是UTF-8编码的一部分,所以,大量只支持ASCII编码的历史遗留软件可以在UTF-8编码下继续工作。</p>
<p>在计算机内存中,统一使用Unicode编码,当需要保存到硬盘或者需要传输的时候,就转换为UTF-8编码。</p>
<p>用记事本编辑的时候,从文件读取的UTF-8字符被转换为Unicode字符到内存里,编辑完成后,保存的时候再把Unicode转换为UTF-8保存到文件。</p>
<p>浏览网页的时候,服务器会把动态生成的Unicode内容转换为UTF-8再传输到浏览器</p>
<p>ord()函数获取字符的整数表示,chr()函数把编码转换为对应的字符:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="nb">ord</span><span class="p">(</span><span class="s">'A'</span><span class="p">)</span>
<span class="mi">65</span>
<span class="o">>>></span> <span class="nb">ord</span><span class="p">(</span><span class="s">'中'</span><span class="p">)</span>
<span class="mi">20013</span>
<span class="o">>>></span> <span class="nb">chr</span><span class="p">(</span><span class="mi">66</span><span class="p">)</span>
<span class="s">'B'</span>
<span class="o">>>></span> <span class="nb">chr</span><span class="p">(</span><span class="mi">25991</span><span class="p">)</span>
<span class="s">'文'</span>
</code></pre></div></div>
<p>bytes类型的数据用带b前缀的单引号或双引号表示,byte里只能是asill码:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">x</span> <span class="o">=</span> <span class="sa">b</span><span class="s">'ABC'</span>
<span class="o">>>></span> <span class="sa">b</span><span class="s">'中文'</span>
<span class="n">File</span> <span class="s">""</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span>
<span class="nb">SyntaxError</span><span class="p">:</span> <span class="nb">bytes</span> <span class="n">can</span> <span class="n">only</span> <span class="n">contain</span> <span class="n">ASCII</span> <span class="n">literal</span> <span class="n">characters</span><span class="p">.</span>
<span class="o">>>></span> <span class="sa">b</span><span class="s">'</span><span class="se">\xd6\xd0</span><span class="s">'</span>
<span class="sa">b</span><span class="s">'</span><span class="se">\xd6\xd0</span><span class="s">'</span>
</code></pre></div></div>
<p>以Unicode表示的str通过encode()方法可以编码为指定的bytes,相应的有decode方法:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="s">'ABC'</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'ascii'</span><span class="p">)</span>
<span class="sa">b</span><span class="s">'ABC'</span>
<span class="o">>>></span> <span class="s">'中文'</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
<span class="sa">b</span><span class="s">'</span><span class="se">\xe4\xb8\xad\xe6\x96\x87</span><span class="s">'</span>
<span class="o">>>></span> <span class="s">'中文'</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'ascii'</span><span class="p">)</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">""</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span>
<span class="nb">UnicodeEncodeError</span><span class="p">:</span> <span class="s">'ascii'</span> <span class="n">codec</span> <span class="n">can</span><span class="s">'t encode characters in position 0-1: ordinal not in range(128)
>>> b'</span>\<span class="n">xd6</span>\<span class="n">xd0</span><span class="s">'.decode('</span><span class="n">gb2312</span><span class="s">')
'</span><span class="n">中</span><span class="s">'
</span></code></pre></div></div>
<p>len()用来计算字符串所占的字节数</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="nb">len</span><span class="p">(</span><span class="sa">b</span><span class="s">'ABC'</span><span class="p">)</span>
<span class="mi">3</span>
<span class="o">>>></span> <span class="nb">len</span><span class="p">(</span><span class="s">'中文'</span><span class="p">.</span><span class="n">encode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span>
<span class="mi">6</span>
</code></pre></div></div>
<p>当Python解释器读取源代码时,为了让它按UTF-8编码读取(保存的源码应该是也UTF-8),我们通常在文件开头写上这句:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># -*- coding: utf-8 -*-
</span></code></pre></div></div>
<p>格式化</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="s">'Hello, %s'</span> <span class="o">%</span> <span class="s">'world'</span>
<span class="s">'Hello, world'</span>
<span class="o">>>></span> <span class="s">'Hi, %s, you have $%d.'</span> <span class="o">%</span> <span class="p">(</span><span class="s">'Michael'</span><span class="p">,</span> <span class="mi">1000000</span><span class="p">)</span>
<span class="s">'Hi, Michael, you have $1000000.'</span>
</code></pre></div></div>
<p>或者</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="s">'Hello, {0}, 成绩提升了 {1:.1f}%'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="s">'小明'</span><span class="p">,</span> <span class="mf">17.125</span><span class="p">)</span>
<span class="s">'Hello, 小明, 成绩提升了 17.1%'</span>
</code></pre></div></div>
<p>%d 整数
%f 浮点数
%s 字符串
%x 十六进制整数</p>
python(数据类型和变量)
2018-03-23T16:28:38+00:00
https://blog.lisong.hn.cn/python%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2018/03/23/python(数据类型和变量)
<p>用r’‘表示’‘内部的字符串默认不转义</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="s">'</span><span class="se">\\\t\\</span><span class="s">'</span><span class="p">)</span>
\ \
<span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="sa">r</span><span class="s">'\\\t\\'</span><span class="p">)</span>
\\\<span class="n">t</span>\\
</code></pre></div></div>
<p>’'’…’'’的格式表示多行内容</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">print</span><span class="p">(</span><span class="s">'''line1
... line2
... line3'''</span><span class="p">)</span>
<span class="n">line1</span>
<span class="n">line2</span>
<span class="n">line3</span>
</code></pre></div></div>
<p>布尔值:True、False</p>
<p>关系运算符:and、or和not</p>
<p>空值:None</p>
<p>变量不需要声明:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">a</span><span class="o">=</span><span class="s">'123'</span>
</code></pre></div></div>
<p>/除法计算结果是浮点数,即使是两个整数恰好整除,结果也是浮点数:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="mi">9</span> <span class="o">/</span> <span class="mi">3</span>
<span class="mf">3.0</span>
</code></pre></div></div>
<p>地板除//,只保留整数部分
```python</p>
<blockquote>
<blockquote>
<blockquote>
<p>10 // 3
3</p>
</blockquote>
</blockquote>
</blockquote>
css-2d矩阵变换matirc公式
2018-03-03T04:51:47+00:00
https://blog.lisong.hn.cn/css/2018/03/03/css-2d矩阵变换matirc公式
<h2 id="矩阵变换原理">矩阵变换原理:</h2>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2018-03-03-css-2d矩阵变换matirc公式-1.gif" alt="" /></p>
<h2 id="translate">translate</h2>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">transform</span><span class="o">:</span> <span class="nt">matrix</span><span class="o">(</span><span class="err">1</span><span class="o">,</span> <span class="err">0</span><span class="o">,</span> <span class="err">0</span><span class="o">,</span> <span class="err">1</span><span class="o">,</span> <span class="nt">水平偏移距离</span><span class="o">,</span> <span class="nt">垂直偏移距离</span><span class="o">);</span>
</code></pre></div></div>
<p>例(x,y都增加30px):</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>transform: matrix(1, 0, 0, 1, 30, 30); /* a=1, b=0, c=0, d=1, e=30, f=30 */
</code></pre></div></div>
<h2 id="rotate">rotate</h2>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">transform</span><span class="o">:</span> <span class="nt">matrix</span><span class="o">(</span><span class="nt">cosθ</span><span class="o">,</span> <span class="nt">sinθ</span><span class="o">,</span> <span class="nt">-sinθ</span><span class="o">,</span> <span class="nt">consθ</span><span class="o">,</span> <span class="err">0</span><span class="o">,</span> <span class="err">0</span><span class="o">);</span><span class="c">/*θ代表旋转的角度,默认顺时针*/</span>
</code></pre></div></div>
<h2 id="skew">skew</h2>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">transform</span><span class="o">:</span> <span class="nt">matrix</span><span class="o">(</span><span class="err">1</span><span class="o">,</span> <span class="nt">tanθy</span><span class="o">,</span> <span class="nt">tanθx</span><span class="o">,</span> <span class="err">1</span><span class="o">,</span> <span class="err">0</span><span class="o">,</span> <span class="err">0</span><span class="o">);</span><span class="c">/*θy代表y轴偏离的角度,θx代表x轴偏离的角度,两者没有关联*/</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2018-03-03-css-2d矩阵变换matirc公式-2.jpg" alt="" /></p>
移动端点击穿透
2018-02-27T12:17:01+00:00
https://blog.lisong.hn.cn/code/2018/02/27/移动端点击穿透
<blockquote>
<p>移动端click事件发生在touchend事件之后,比touchend延迟300ms,之所以这样,是为了捕获双击事件(用于放大屏幕),为了缩小这个延迟,可以用touch事件模拟click,这将造成点击穿透问题。</p>
</blockquote>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></span>点击穿透<span class="nt"></title></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nt">html</span><span class="o">,</span><span class="nt">body</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.div1</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="m">#999</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.div2</span><span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">fixed</span><span class="p">;</span>
<span class="nl">top</span><span class="p">:</span><span class="m">35%</span><span class="p">;</span>
<span class="nl">left</span><span class="p">:</span> <span class="m">25%</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">30%</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">50%</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></div></span>
<span class="nt"></body></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"zepto.min.js"</span><span class="nt">></script></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">src=</span><span class="s">"touch.js"</span><span class="nt">></script></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">.div2</span><span class="dl">'</span><span class="p">).</span><span class="nx">tap</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">div2 tap</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">.div2</span><span class="dl">'</span><span class="p">).</span><span class="nx">hide</span><span class="p">();</span>
<span class="p">})</span>
<span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">.div1</span><span class="dl">'</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">div1 click</span><span class="dl">'</span><span class="p">);</span>
<span class="p">})</span>
<span class="nt"></script></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>点击红色div2,将触发tap事件,然后继续触发click事件,之所以这样,是因为zepto的tap事件其实就是监听的touchend事件,然后在250ms之后触发tap,而click事件是300ms之后,这样缩小了click的延迟时间。这里在触发tap的时候隐藏掉了div2,300ms后click触发,此时div2已经隐藏了,手指点击的位置变成了div1,因此触发了div1的click事件。</p>
<p>要避免这种事件穿透,有两种方法:</p>
<ul>
<li>js实现,当点击div2的时候,动态的生成一个透明的div层,覆盖在div1上,300ms后删除。</li>
<li>css实现,当点击div2的时候,给div1设置css3属性pointer-events:none(这么设置将是div1变成穿透的,所以其上的事件都不会触发),300ms还原pointer-events:auto。</li>
</ul>
HTTP缓存
2018-02-26T06:45:39+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2018/02/26/HTTP缓存
<h2 id="http请求过程">http请求过程</h2>
<p><img src="https://wanls4583.github.io/images/posts/其他/2018-02-26-HTTP缓存-1.jpg" alt="" /></p>
<p>http缓存分为强制缓存和对比缓存。强制缓存相关的字段有Expires,Cache-Control;对比缓存相关的字段有Last-Modified/If-Modified-Since,Etag/If-None-Match。对比缓存只有在强制缓存失效后才会去与服务器进行交互,如果验证通过(资源未被修改),则返回304,否则返回最新的资源(200)。</p>
<h2 id="expires">Expires</h2>
<p>由服务器端返回,表示该资源将于什么时间过期。Expires 是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。Expires 的一个缺点就是,返回的到期时间是服务器端的时间,这样存在一个问题,比较的时间是客户端本地设置的时间,所以有可能会导致差错,所以在HTTP 1.1版开始,使用Cache-Control替代。</p>
<h2 id="cache-control">Cache-Control</h2>
<p>用于定义所有的缓存机制都必须遵循的缓存指示,Cache-Control优先级高于Expires。
<img src="https://wanls4583.github.io/images/posts/其他/2018-02-26-HTTP缓存-2.jpg" alt="" />
no-cache每次请求都会触发对比缓存的交互,no-store每次请求服务器都会返回最新的资源。</p>
<h2 id="last-modifiedif-modified-since">Last-Modified/If-Modified-Since</h2>
<p>Last-Modified是由服务器端返回的一个http头,代表了该资源最后被修改的时间,浏览器会记录该字段,当强制缓存失效后,再次请求该资源时,浏览器会带上If-Modified-Since头,If-Modified-Since的值就是上次服务器返回的Last-Modified,服务器对比资源的最后修改时间是否大于If-Modified-Since,如果大于If-Modified-Since,证明资源已经被修改,则返回最新的资源,状态码置为200,如果小于If-Modified-Since,证明资源未被修改,直接返回304状态码,浏览器收到304后会从缓存取资源。</p>
<h2 id="etagif-none-match">Etag/If-None-Match</h2>
<p>Etag头代表了该资源的唯一标识,每次资源被修改,Etag也会更改。Etag的作用和Last-Modified的作用一样,也是用来判断资源是否被修改,当强制缓存失效后,再次请求资源时,浏览器会带上If-None-Match,其值为上次服务器返回的Etag。不过Last-Modified只能精确到秒,如果在同一秒里对资源进行了两次修改,服务器通过If-Modified-Since是不能判断出资源已经被再次修改了,所以才有了Etag。另外,Etag的优先级高于Last-Modified。</p>
<h2 id="用户操作对缓存的影响">用户操作对缓存的影响</h2>
<p><img src="https://wanls4583.github.io/images/posts/其他/2018-02-26-HTTP缓存-3.png" alt="" />
这个图是网上总结的,不过通过实际验证发现F5/刷新后,Cache-Control/Expires依然有效。Ctrl+F5时,浏览器请求头会带上Cache-Control字段,值为no-cache。</p>
js深拷贝
2018-02-25T07:03:51+00:00
https://blog.lisong.hn.cn/code/2018/02/25/js深拷贝
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{</span><span class="na">a</span><span class="p">:</span><span class="mi">1</span><span class="p">};</span>
<span class="kd">var</span> <span class="nx">obj1</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">b</span><span class="p">:</span><span class="mi">2</span><span class="p">,</span>
<span class="na">c</span><span class="p">:</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="mi">3</span><span class="p">;</span>
<span class="p">},</span>
<span class="na">d</span><span class="p">:</span><span class="nx">obj</span><span class="p">,</span>
<span class="na">e</span><span class="p">:[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">],</span>
<span class="na">f</span><span class="p">:</span><span class="kc">null</span><span class="p">,</span>
<span class="na">g</span><span class="p">:</span><span class="kc">undefined</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">copy_1</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="p">{};</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">obj</span> <span class="o">&&</span> <span class="k">typeof</span> <span class="nx">obj</span> <span class="o">==</span> <span class="dl">'</span><span class="s1">object</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">obj</span> <span class="k">instanceof</span> <span class="nb">Array</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">result</span> <span class="o">=</span> <span class="p">[];</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">key</span> <span class="k">in</span> <span class="nx">obj</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">result</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span> <span class="o">=</span> <span class="nx">copy_1</span><span class="p">(</span><span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">result</span> <span class="o">=</span> <span class="nx">obj</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//使用JSON实现拷贝,将会忽略function和undefined</span>
<span class="kd">function</span> <span class="nx">copy_2</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">JSON</span><span class="p">.</span><span class="nx">parse</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">stringify</span><span class="p">(</span><span class="nx">obj</span><span class="p">));</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">copy_1</span><span class="p">(</span><span class="nx">obj1</span><span class="p">));</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">copy_2</span><span class="p">(</span><span class="nx">obj1</span><span class="p">));</span>
</code></pre></div></div>
Object特性
2018-02-22T10:08:53+00:00
https://blog.lisong.hn.cn/code/2018/02/22/Object特性
<h2 id="defineproperty">defineProperty</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="nx">tmp</span> <span class="o">=</span> <span class="kc">undefined</span><span class="p">;</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">defineProperty</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span><span class="dl">'</span><span class="s1">a</span><span class="dl">'</span><span class="p">,{</span>
<span class="c1">//该属性是否可枚举(for in,Object.keys),默认为false</span>
<span class="na">enumerable</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="c1">//该属性的特性是否可修改(除writable特性外的其他特性是否可以被修改,</span>
<span class="c1">//如重新定义enumerable,configurable等属性),默认为false</span>
<span class="na">configurable</span><span class="p">:</span> <span class="kc">false</span><span class="p">,</span>
<span class="c1">//该属性是否可读写,默认为false,不能与set或get同时存在</span>
<span class="c1">// writable: true</span>
<span class="c1">//属性的值,不能与set或get同时存在</span>
<span class="c1">// value: 1,</span>
<span class="c1">//setter</span>
<span class="na">set</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">set:</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">value</span><span class="p">);</span>
<span class="nx">tmp</span> <span class="o">=</span> <span class="nx">value</span><span class="p">;</span>
<span class="p">},</span>
<span class="c1">//getter</span>
<span class="na">get</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">value</span><span class="p">){</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">get:</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">tmp</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">b</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">a</span> <span class="o">=</span> <span class="mi">3</span><span class="p">;</span><span class="c1">//set:3</span>
<span class="c1">// Object.defineProperty(obj, "a", {enumerable : true});//TypeError</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">obj</span><span class="p">));</span><span class="c1">//["b"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">a</span><span class="p">);</span><span class="c1">//get:3</span>
</code></pre></div></div>
<h2 id="create">create</h2>
<p>create类似寄生构造函数</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">p</span> <span class="o">=</span> <span class="p">{</span><span class="na">a</span><span class="p">:</span><span class="mi">1</span><span class="p">};</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">p</span><span class="p">,</span> <span class="p">{</span><span class="c1">//可以在obj上追加属性</span>
<span class="na">b</span><span class="p">:</span> <span class="p">{</span>
<span class="na">value</span><span class="p">:</span> <span class="mi">2</span><span class="p">,</span>
<span class="na">writable</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">enumerable</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">configurable</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">__proto__</span><span class="o">==</span><span class="nx">p</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">a</span><span class="p">);</span><span class="c1">//1</span>
<span class="c1">//Object.create的简单实现</span>
<span class="kd">function</span> <span class="nx">create</span><span class="p">(</span><span class="nx">p</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">F</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="nx">F</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nx">p</span><span class="p">;</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">F</span><span class="p">();</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">p</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">__proto__</span><span class="o">==</span><span class="nx">p</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">a</span><span class="p">);</span><span class="c1">//1</span>
</code></pre></div></div>
<h2 id="assign">assign</h2>
<p>Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖。Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">s1</span> <span class="o">=</span> <span class="p">{</span><span class="na">a</span><span class="p">:</span><span class="dl">'</span><span class="s1">a1</span><span class="dl">'</span><span class="p">,</span><span class="na">b</span><span class="p">:</span><span class="mi">2</span><span class="p">};</span>
<span class="kd">var</span> <span class="nx">s2</span> <span class="o">=</span> <span class="p">{</span><span class="na">a</span><span class="p">:</span><span class="dl">'</span><span class="s1">a2</span><span class="dl">'</span><span class="p">,</span><span class="na">c</span><span class="p">:</span><span class="mi">3</span><span class="p">};</span>
<span class="kd">var</span> <span class="nx">s3</span> <span class="o">=</span> <span class="p">{</span><span class="na">a</span><span class="p">:</span><span class="dl">'</span><span class="s1">a3</span><span class="dl">'</span><span class="p">,</span><span class="na">d</span><span class="p">:</span><span class="mi">4</span><span class="p">};</span>
<span class="kd">var</span> <span class="nx">tmp</span> <span class="o">=</span> <span class="p">{};</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">assign</span><span class="p">(</span><span class="nx">tmp</span><span class="p">,</span><span class="nx">s1</span><span class="p">,</span><span class="nx">s2</span><span class="p">,</span><span class="nx">s3</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="o">==</span><span class="nx">tmp</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">);</span><span class="c1">//{a: "a3", b: 2, c: 3, d: 4}</span>
<span class="c1">//assgin的简单实现</span>
<span class="kd">function</span> <span class="nx">assign</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">arg</span> <span class="o">=</span> <span class="nx">arguments</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">target</span> <span class="o">=</span> <span class="nx">arg</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="nx">i</span><span class="o"><</span><span class="nx">arg</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
<span class="nx">copy</span><span class="p">(</span><span class="nx">arg</span><span class="p">[</span><span class="nx">i</span><span class="p">]);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">copy</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">key</span> <span class="k">in</span> <span class="nx">obj</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="nx">key</span><span class="p">)){</span>
<span class="nx">target</span><span class="p">[</span><span class="nx">key</span><span class="p">]</span><span class="o">=</span><span class="nx">obj</span><span class="p">[</span><span class="nx">key</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">target</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="nx">assign</span><span class="p">(</span><span class="nx">tmp</span><span class="p">,</span><span class="nx">s1</span><span class="p">,</span><span class="nx">s2</span><span class="p">,</span><span class="nx">s3</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="o">==</span><span class="nx">tmp</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">);</span><span class="c1">//{a: "a3", b: 2, c: 3, d: 4}</span>
</code></pre></div></div>
<h2 id="枚举">枚举</h2>
<p>for in和Object.keys()都可以枚举对象的可枚举属性(enumerable为true),不过Object.keys()只能枚举对象的自身属性,而for in可以枚举原型链上的属性</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">tmp</span> <span class="o">=</span> <span class="p">{</span><span class="na">a</span><span class="p">:</span><span class="mi">1</span><span class="p">};</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">create</span><span class="p">(</span><span class="nx">tmp</span><span class="p">,{</span>
<span class="dl">'</span><span class="s1">b</span><span class="dl">'</span><span class="p">:{</span>
<span class="na">enumerable</span><span class="p">:</span><span class="kc">true</span><span class="p">,</span>
<span class="na">value</span><span class="p">:</span><span class="mi">2</span>
<span class="p">},</span>
<span class="dl">'</span><span class="s1">c</span><span class="dl">'</span><span class="p">:{</span>
<span class="na">enumerable</span><span class="p">:</span><span class="kc">false</span><span class="p">,</span>
<span class="na">value</span><span class="p">:</span><span class="mi">3</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">keys</span><span class="p">(</span><span class="nx">obj</span><span class="p">));</span><span class="c1">//["b"]</span>
<span class="nx">tmp</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">key</span> <span class="k">in</span> <span class="nx">obj</span><span class="p">){</span>
<span class="nx">tmp</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">key</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">tmp</span><span class="p">);</span><span class="c1">//["a","b"]</span>
</code></pre></div></div>
基于MP3加密音频文件的在线H5播放器的实现
2017-12-30T06:16:55+00:00
https://blog.lisong.hn.cn/%E9%9F%B3%E8%A7%86%E9%A2%91/2017/12/30/基于MP3加密音频文件的在线H5播放器的实现
<blockquote>
<p>引言:随着知识付费项目的市场份额逐渐扩大,对于音频产品的在线播放需求也在提升,怎么做到既能支持独家音频的web在线播放又能防止音频被盗链、被下载成了音频相关类产品web端的核心技术。</p>
</blockquote>
<p>目前,纵观市面上的音频产品的web端鲜有做到对音频加密的地步,为了防止音频被盗用,对于付费内的资源,大多数是引导用于去APP里付费和使用。而很多产品的推广其实是通过微信公众号的形式进行的,如果能够直接在微信H5端进行一些常用的产品流程(加密音频的付费、播放),可增加更好的用户体验。</p>
<p>在web端,传统的Audio对象提供的API功能有限,并不能满足对于高要求的音频播放功能。鉴于此,经过探索和技术调研,我们团队独立研发了可用于线上产品的基于H5的加密音频文件的在线播放器。该技术的核心功能是基于H5的核心API:AudioContext。AudioContext是H5提供的对于音频数据直接进行操作的一套API,通过这一套API可以对音频数据进行修改和解码等操作。因为可以接触到音频数据的底层,因此我们可以在后台对音频数据进行加密,在前端先解密字节流,然后再调用AudioContext去进行解码等操作。</p>
<p>我们已经知道了用AudioContext能够进行解码工作,但是要做到在线播放功能还有很长一段路要走。因为AudioContext不支持自动拉取数据,因此要做到在线播放的功能,只能我们自己去实现数据的拉取,在这里可以使用ajax配合range分段加载音频数据,再配合后台的动态key,对拉取的进行对称解密。</p>
<p>一个完整的播放器应该是能够拖动播放的,这是播放器的核心功能,也是技术的难点,因为不同音频的格式是不一样,要做到定点播放,需要对音频的元数据进行解析,获取音频的总时长,比特率等,利用这些元数据,再根据拖动的百分比就可以计算出应该加载哪一段数据。当然对于不同的音频格式,需要解析的元数据是不一样,目前,我们只是针对MP3文件进行了元数据的解析。</p>
<p>用AudioContext除了可以解码音频数据外,甚至可以更改音频的音色,音调,也就是说你可以用它开发一个在线的音频工作室。更甚至,你可以无中生有,创造声音(前提是你对音调,波形有较好的理解)。基本上你可以想到的对音频的处理,它都可以解决,虽然目前只有移动端和PC端高级浏览器支持AudioContext,但随着低版本浏览器的淘汰,其运用的场景将越来越广,目前很多手机游戏都是用它来实现音效的播放,我们有理由相信,其将成为音视频的主流技术。</p>
nodejs 实现静态服务器(支持媒体播放)
2017-11-26T05:03:21+00:00
https://blog.lisong.hn.cn/nodejs/2017/11/26/nodejs 实现静态服务器(支持媒体播放)
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">const</span> <span class="nx">http</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">http</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">fs</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">path</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">const</span> <span class="nx">mime</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">mime</span><span class="dl">'</span><span class="p">);</span><span class="c1">//根据文件后缀获取文件类型工具</span>
<span class="kd">const</span> <span class="nx">server</span> <span class="o">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">createServer</span><span class="p">((</span><span class="nx">req</span><span class="p">,</span> <span class="nx">res</span><span class="p">)</span> <span class="o">=></span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">realPath</span> <span class="o">=</span> <span class="nx">__dirname</span><span class="o">+</span><span class="nx">req</span><span class="p">.</span><span class="nx">url</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">exist</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">existsSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">exist</span><span class="p">){</span>
<span class="nx">sendFile</span><span class="p">(</span><span class="nx">realPath</span><span class="p">,</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">404</span><span class="p">,</span><span class="dl">'</span><span class="s1">file not exist</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">server</span><span class="p">.</span><span class="nx">listen</span><span class="p">(</span><span class="mi">8000</span><span class="p">);</span>
<span class="kd">function</span> <span class="nx">sendFile</span><span class="p">(</span><span class="nx">realPath</span><span class="p">,</span><span class="nx">req</span><span class="p">,</span><span class="nx">res</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">stat</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">statSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="c1">//判断是请求头中是否有range部分</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">range</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">size</span> <span class="o">=</span> <span class="nx">stat</span><span class="p">.</span><span class="nx">size</span><span class="p">;</span> <span class="c1">//获取文件大小</span>
<span class="c1">//暂且写在这里</span>
<span class="kd">function</span> <span class="nx">getRange</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">range</span> <span class="o">=</span> <span class="nx">req</span><span class="p">.</span><span class="nx">headers</span><span class="p">.</span><span class="nx">range</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">range</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="dl">"</span><span class="s2">,</span><span class="dl">"</span><span class="p">)</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//这里只处理了一个分段的情况</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//range大约长这样子:bytes=0-255[,256-511]</span>
<span class="kd">var</span> <span class="nx">parts</span> <span class="o">=</span> <span class="nx">range</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/bytes=/</span><span class="p">,</span> <span class="dl">''</span><span class="p">).</span><span class="nx">split</span><span class="p">(</span><span class="dl">"</span><span class="s2">-</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">partiaStart</span> <span class="o">=</span> <span class="nx">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">partialEnd</span> <span class="o">=</span> <span class="nx">parts</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">start</span> <span class="o">=</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">partiaStart</span><span class="p">);</span> <span class="c1">//起始位置</span>
<span class="c1">//如果是bytes=0-,就是整个文件大小了</span>
<span class="kd">var</span> <span class="nx">end</span> <span class="o">=</span> <span class="nx">partialEnd</span> <span class="p">?</span> <span class="nb">parseInt</span><span class="p">(</span><span class="nx">partialEnd</span><span class="p">)</span> <span class="p">:</span> <span class="nx">size</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="nx">start</span><span class="p">)</span> <span class="o">||</span> <span class="nb">isNaN</span><span class="p">(</span><span class="nx">end</span><span class="p">))</span> <span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="c1">//分段的大小</span>
<span class="kd">var</span> <span class="nx">chunkSize</span> <span class="o">=</span> <span class="nx">end</span> <span class="o">-</span> <span class="nx">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">return</span> <span class="p">{</span> <span class="dl">'</span><span class="s1">start</span><span class="dl">'</span><span class="p">:</span> <span class="nx">start</span><span class="p">,</span> <span class="dl">'</span><span class="s1">end</span><span class="dl">'</span><span class="p">:</span> <span class="nx">end</span><span class="p">,</span> <span class="dl">'</span><span class="s1">chunkSize</span><span class="dl">'</span><span class="p">:</span> <span class="nx">chunkSize</span> <span class="p">};</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">rangeData</span> <span class="o">=</span> <span class="nx">getRange</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">rangeData</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">//createReadStream原生支持range</span>
<span class="kd">var</span> <span class="nx">raw</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">createReadStream</span><span class="p">(</span><span class="nx">realPath</span><span class="p">,</span> <span class="p">{</span> <span class="dl">'</span><span class="s1">start</span><span class="dl">'</span><span class="p">:</span> <span class="nx">rangeData</span><span class="p">.</span><span class="nx">start</span><span class="p">,</span> <span class="dl">'</span><span class="s1">end</span><span class="dl">'</span><span class="p">:</span> <span class="nx">rangeData</span><span class="p">.</span><span class="nx">end</span> <span class="p">});</span>
<span class="c1">//状态码当然是206了</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">206</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Partial Content</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="nx">mime</span><span class="p">.</span><span class="nx">getType</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">realPath</span><span class="p">)),</span>
<span class="dl">'</span><span class="s1">Content-Range</span><span class="dl">'</span><span class="p">:</span> <span class="dl">'</span><span class="s1">bytes </span><span class="dl">'</span> <span class="o">+</span> <span class="nx">rangeData</span><span class="p">.</span><span class="nx">start</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">-</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">rangeData</span><span class="p">.</span><span class="nx">end</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">/</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">size</span><span class="p">,</span>
<span class="dl">'</span><span class="s1">Content-Length</span><span class="dl">'</span><span class="p">:</span> <span class="nx">rangeData</span><span class="p">.</span><span class="nx">chunkSize</span>
<span class="p">});</span>
<span class="nx">raw</span><span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">res</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">416</span><span class="p">,</span> <span class="dl">"</span><span class="s2">not ok!</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">send media file:</span><span class="dl">'</span><span class="o">+</span><span class="nx">realPath</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">file</span> <span class="o">=</span> <span class="nx">fs</span><span class="p">.</span><span class="nx">readFileSync</span><span class="p">(</span><span class="nx">realPath</span><span class="p">);</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">writeHead</span><span class="p">(</span><span class="mi">200</span><span class="p">,</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">Content-Type</span><span class="dl">'</span><span class="p">:</span> <span class="nx">mime</span><span class="p">.</span><span class="nx">getType</span><span class="p">(</span><span class="nx">path</span><span class="p">.</span><span class="nx">basename</span><span class="p">(</span><span class="nx">realPath</span><span class="p">)),</span>
<span class="p">});</span>
<span class="nx">res</span><span class="p">.</span><span class="nx">end</span><span class="p">(</span><span class="nx">file</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">send static file:</span><span class="dl">'</span><span class="o">+</span><span class="nx">realPath</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">listen 8000</span><span class="dl">'</span><span class="p">)</span>
</code></pre></div></div>
webpack加载器与插件开发简单案例
2017-11-10T10:41:29+00:00
https://blog.lisong.hn.cn/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/2017/11/10/webpack加载器与插件开发简单案例
<blockquote>
<p>如今前端构建已成为大型项目必不可少的一部分,Webpack 是当下最热门的前端资源模块化管理和打包工具。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader 的转换,任何形式的资源都可以视作模块。而传统的构建工具(gulp,graunt…)是不具备理解依赖的能力的。</p>
</blockquote>
<h2 id="加载器">加载器</h2>
<p>loader(加载器)是webpack运行的关键部分,有了loader就可以加载各种我们想处理的资源了。加载器可以单独使用也可以多个配合使用,当多个loaders被链接的时候,只有最后一个loader能够获取资源文件并且只有第一个loader预期返回一个或者两个值(JavaScript和SourceMap)。其它任何loader返回的值会传到之前的loader中。一个简单的css文件加载器的代码如下:</p>
<p>my-trim-loader:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//处理换行符</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">source</span><span class="p">){</span>
<span class="c1">// return source.replace(/\r\n|\r|\n/g,'');//只是传递给下一个架子器,所以不用module.exports</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">module.exports="</span><span class="dl">'</span><span class="o">+</span><span class="nx">source</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\r\n</span><span class="sr">|</span><span class="se">\r</span><span class="sr">|</span><span class="se">\n</span><span class="sr">/g</span><span class="p">,</span><span class="dl">''</span><span class="p">)</span><span class="o">+</span><span class="dl">'</span><span class="s1">"</span><span class="dl">'</span><span class="p">;</span><span class="c1">//将作为一个单独的依赖输出到最终的文件中</span>
<span class="p">}</span>
</code></pre></div></div>
<p>my-style-loader:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">loaderUtils</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">loader-utils</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">path</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">source</span><span class="p">){</span>
<span class="c1">// return 'require('+loaderUtils.stringifyRequest(this,path.resolve(__dirname,'./add-style'))+')("'+source+'");'</span>
<span class="p">}</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="p">.</span><span class="nx">pitch</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">request</span><span class="p">){</span>
<span class="k">return</span> <span class="s2">`var source = require(</span><span class="p">${</span><span class="nx">loaderUtils</span><span class="p">.</span><span class="nx">stringifyRequest</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="dl">'</span><span class="s1">!</span><span class="dl">'</span><span class="o">+</span><span class="nx">request</span><span class="p">)}</span><span class="s2">);var addStyle = require(</span><span class="p">${</span><span class="nx">loaderUtils</span><span class="p">.</span><span class="nx">stringifyRequest</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span><span class="dl">'</span><span class="s1">./add-style</span><span class="dl">'</span><span class="p">))}</span><span class="s2">);addStyle(source)`</span>
<span class="p">}</span>
</code></pre></div></div>
<p>中间的加载器可以使用默认的方式接受上一个加载器传递过来的处理结果,也可以添加一个pitch方法接收一个request路径,如果pitch方法有返回结果,那么将覆盖默认的返回结果。定义了pitch方法就可以通过require的方式引入上个加载器的处理结果,因为是加载器,所以前面需要加一个‘!’。以request这种方式,那么上一个加载器的处理结果应该作为一个单独的依赖输出到最终的文件中。为了避免产生较长的字符串,这里引入了add-style来处理实际的代码。</p>
<p>add-style:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">source</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">styleReg</span> <span class="o">=</span> <span class="sr">/</span><span class="se">(</span><span class="sr">.+</span><span class="se">)\{([\s\s]</span><span class="sr">+</span><span class="se">)\}</span><span class="sr">/</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">style</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createElement</span><span class="p">(</span><span class="dl">'</span><span class="s1">style</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">box</span><span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">createTextNode</span><span class="p">(</span><span class="nx">source</span><span class="p">);</span> <span class="c1">//IE6-8不支持</span>
<span class="nx">style</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">text/css</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">style</span><span class="p">.</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">box</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="dl">'</span><span class="s1">head</span><span class="dl">'</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">appendChild</span><span class="p">(</span><span class="nx">style</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>最后只需要在webpack.config.js里配置下处理规则就可以使用一个简单的css资源加载器了:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nx">resolveLoader</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">modules</span><span class="p">:</span> <span class="p">[</span> <span class="dl">"</span><span class="s2">custom_loaders</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">node_modules</span><span class="dl">"</span><span class="p">]</span><span class="c1">//用来定义搜索加载器的路径</span>
<span class="p">},</span>
<span class="nx">module</span><span class="p">:</span> <span class="p">{</span>
<span class="nl">loaders</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span> <span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">css$/</span><span class="p">,</span> <span class="na">loader</span><span class="p">:</span> <span class="dl">"</span><span class="s2">my-style-loader!my-trim-loader</span><span class="dl">"</span> <span class="p">}</span><span class="c1">//处理顺序从右向左</span>
<span class="p">]</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="插件">插件</h2>
<p>插件向第三方开发者提供了 webpack 引擎中完整的能力。使用阶段式的构建回调,开发者可以引入它们自己的行为到 webpack 构建流程中。</p>
<p>在插件开发中最重要的两个资源就是 compiler 和 compilation 对象。理解它们的角色是扩展 webpack 引擎重要的第一步。</p>
<ul>
<li>
<p>compiler对象代表了完整的 webpack 环境配置。这个对象在启动 webpack 时被一次性建立,并在所有可操作的设置中被配置,包括原始配置,加载器和插件。当在 webpack 环境中应用一个插件时,插件将收到一个编译器对象的引用。可以使用它来访问 webpack 的主环境。</p>
</li>
<li>
<p>compilation对象代表了一次单一的版本构建和生成资源一个编译对象表现了当前的模块资源、编译生成资源、变化的文件、以及被跟踪依赖的状态信息。编译对象也提供了很多关键点回调供插件做自定义处理时选择使用。</p>
</li>
</ul>
<p>一个简单的在项目根目录下生成如果页面index.html的插件代码如下:</p>
<p>myHtmlPlugin:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">fs</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">fs</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">function</span> <span class="nx">MyHtmlPlugin</span><span class="p">(</span><span class="nx">options</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// 根据 options 配置你的插件</span>
<span class="p">}</span>
<span class="nx">MyHtmlPlugin</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">apply</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">compiler</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">compiler</span><span class="p">.</span><span class="nx">plugin</span><span class="p">(</span><span class="dl">"</span><span class="s2">emit</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(</span><span class="nx">compilation</span><span class="p">,</span> <span class="nx">callback</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">The compilation is going to emit files...</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">context</span> <span class="o">=</span> <span class="nx">compiler</span><span class="p">.</span><span class="nx">context</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">html</span> <span class="o">=</span> <span class="s2">`
<!DOCTYPE html>
<html>
<head>
<title>webpack test1</title>
</head>
<body>
<script type="text/javascript" src="</span><span class="p">${</span><span class="nx">compiler</span><span class="p">.</span><span class="nx">options</span><span class="p">.</span><span class="nx">output</span><span class="p">.</span><span class="nx">filename</span><span class="p">}</span><span class="s2">"></script>
</body>
</html>
`</span><span class="p">;</span>
<span class="nx">fs</span><span class="p">.</span><span class="nx">writeFile</span><span class="p">(</span><span class="nx">context</span><span class="o">+</span><span class="dl">'</span><span class="s1">/</span><span class="dl">'</span><span class="o">+</span><span class="dl">'</span><span class="s1">index.html</span><span class="dl">'</span><span class="p">,</span> <span class="nx">html</span><span class="p">);</span>
<span class="nx">callback</span><span class="p">();</span>
<span class="p">});</span>
<span class="p">};</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="nx">MyHtmlPlugin</span><span class="p">;</span>
</code></pre></div></div>
<p>加载器和插件的完整配置如下:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">path</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">path</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">myHtmlPlugin</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./custom_modules/my-html-plugin</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">entry</span><span class="p">:</span> <span class="dl">'</span><span class="s1">./index.js</span><span class="dl">'</span><span class="p">,</span>
<span class="na">output</span><span class="p">:</span> <span class="p">{</span>
<span class="na">path</span><span class="p">:</span> <span class="nx">path</span><span class="p">.</span><span class="nx">resolve</span><span class="p">(</span><span class="nx">__dirname</span><span class="p">,</span> <span class="dl">'</span><span class="s1">./</span><span class="dl">'</span><span class="p">),</span>
<span class="na">filename</span><span class="p">:</span> <span class="dl">'</span><span class="s1">index.bundle.js</span><span class="dl">'</span>
<span class="p">},</span>
<span class="na">resolve</span><span class="p">:</span> <span class="p">{</span>
<span class="na">modules</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">custom_modules</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">node_modules</span><span class="dl">"</span><span class="p">]</span><span class="c1">//定义模块的搜索路径</span>
<span class="p">},</span>
<span class="na">resolveLoader</span><span class="p">:</span> <span class="p">{</span>
<span class="na">modules</span><span class="p">:</span> <span class="p">[</span> <span class="dl">"</span><span class="s2">custom_loaders</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">node_modules</span><span class="dl">"</span><span class="p">]</span><span class="c1">//定义加载器的搜索路径</span>
<span class="p">},</span>
<span class="na">module</span><span class="p">:</span> <span class="p">{</span>
<span class="na">loaders</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span> <span class="na">test</span><span class="p">:</span> <span class="sr">/</span><span class="se">\.</span><span class="sr">css$/</span><span class="p">,</span> <span class="na">loader</span><span class="p">:</span> <span class="dl">"</span><span class="s2">my-style-loader!my-trim-loader</span><span class="dl">"</span> <span class="p">}</span>
<span class="p">]</span>
<span class="p">},</span>
<span class="na">plugins</span><span class="p">:</span> <span class="p">[</span>
<span class="k">new</span> <span class="nx">myHtmlPlugin</span><span class="p">()</span>
<span class="p">]</span>
<span class="p">};</span>
</code></pre></div></div>
<p>完整的代码:<a href="https://github.com/wanls4583/webpack-loader-plugin-demo">https://github.com/wanls4583/webpack-loader-plugin-demo</a></p>
深入理解border-radius
2017-11-08T09:55:14+00:00
https://blog.lisong.hn.cn/css/2017/11/08/深入理解border-radius
<blockquote>
<p>border-radius具有两个特性:大值特性和等比例特性。这两个特性主要用来控制当border-radius的值大于元素的outerWidth或outerHeight时,元素边框的变形行为。</p>
</blockquote>
<h2 id="大值特性">大值特性</h2>
<p>当border-radius值很大的时候只会用元素的最大的宽或高(包括border)来渲染</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"><style></span>
<span class="nt">div</span>
<span class="p">{</span>
<span class="nl">border</span><span class="p">:</span><span class="m">2px</span> <span class="nb">solid</span> <span class="m">#a1a1a1</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span><span class="m">#dddddd</span><span class="p">;</span>
<span class="nl">overflow</span><span class="p">:</span><span class="nb">hidden</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span><span class="m">200px</span> <span class="m">0</span> <span class="m">0</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-08-深入理解border-radius-1.png" alt="" /></p>
<p>改变radius的值:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">div</span>
<span class="p">{</span>
<span class="nl">border</span><span class="p">:</span><span class="m">2px</span> <span class="nb">solid</span> <span class="m">#a1a1a1</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span><span class="m">#dddddd</span><span class="p">;</span>
<span class="nl">overflow</span><span class="p">:</span><span class="nb">hidden</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span><span class="m">300px</span> <span class="m">0</span> <span class="m">0</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-08-深入理解border-radius-2.png" alt="" />
可以看出两段代码的效果都是一样,因为300px已经超过了元素的outerHeight和outerWidth,所以自动变成了200px。</p>
<h2 id="等比例特性">等比例特性</h2>
<h3 id="垂直半径和水平半径的等比例性">垂直半径和水平半径的等比例性</h3>
<p>border-radius定义的某个角的垂直半径和水平半径的比例是不会变的。</p>
<p>其实上面的例子里也用到了这个特性,只是为了将理解力定位在最大值特性,避免等比例特性的干扰,左上角我只设置了一个值,也即垂直半径和水平半径相等,所以体现不出等比例特性,现在我们更改水平半径和垂直半径,使其不相等:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">div</span>
<span class="p">{</span>
<span class="nl">border</span><span class="p">:</span><span class="m">2px</span> <span class="nb">solid</span> <span class="m">#a1a1a1</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span><span class="m">#dddddd</span><span class="p">;</span>
<span class="nl">overflow</span><span class="p">:</span><span class="nb">hidden</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span><span class="m">200px</span> <span class="m">0</span> <span class="m">0</span> <span class="m">0</span><span class="p">/</span><span class="m">400px</span> <span class="m">0</span> <span class="m">0</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-08-深入理解border-radius-3.png" alt="" />
根据最大值特性,垂直半径400px已经超出了元素的outerHeight,所以应该会变为元素的最大高度200px,此时由于等比例特性200/400=1/2,所以水平半径=200px*1/2=100px,所以border-radius:200px 0 0 0/400px 0 0 0其实对应于border-radius:100px 0 0 0/200px 0 0 0。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">div</span>
<span class="p">{</span>
<span class="nl">border</span><span class="p">:</span><span class="m">2px</span> <span class="nb">solid</span> <span class="m">#a1a1a1</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span><span class="m">#dddddd</span><span class="p">;</span>
<span class="nl">overflow</span><span class="p">:</span><span class="nb">hidden</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span><span class="m">100px</span> <span class="m">0</span> <span class="m">0</span> <span class="m">0</span><span class="p">/</span><span class="m">200px</span> <span class="m">0</span> <span class="m">0</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-08-深入理解border-radius-4.png" alt="" />
从结果上也可以看出border-radius:200px 0 0 0/400px 0 0 0和border-radius:100px 0 0 0/200px 0 0 0的效果是一样的。</p>
<p>注意:当border-radius指定的某个角的水平半径和垂直半径都超过元素尺寸的时候,同样遵循这个两个特性。</p>
<h3 id="相邻角的垂直水平半径的等比例性">相邻角的垂直(水平)半径的等比例性</h3>
<p>当相邻角的水平(垂直)半径和超过元素的outWidth(outHeight)时候,将按照等比例缩小半径,直至两相邻角的水平(垂直)半径和等于元素的outWidth(outHeight)。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"><style></span>
<span class="nc">.div1</span>
<span class="p">{</span>
<span class="nl">border</span><span class="p">:</span><span class="m">2px</span> <span class="nb">solid</span> <span class="m">#a1a1a1</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span><span class="m">#dddddd</span><span class="p">;</span>
<span class="nl">overflow</span><span class="p">:</span><span class="nb">hidden</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span><span class="m">300px</span> <span class="m">0</span> <span class="m">0</span> <span class="m">100px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.div2</span>
<span class="p">{</span>
<span class="nl">border</span><span class="p">:</span><span class="m">2px</span> <span class="nb">solid</span> <span class="m">#a1a1a1</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span><span class="m">198px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span><span class="m">#dddddd</span><span class="p">;</span>
<span class="nl">overflow</span><span class="p">:</span><span class="nb">hidden</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span><span class="m">150px</span> <span class="m">0</span> <span class="m">0</span> <span class="m">50px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div1"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"div2"</span><span class="nt">></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-08-深入理解border-radius-5.png" alt="" />
因为300+100已经超出了元素的outerWidth(200)和outerHeight(200),所以按照等比例(3/1)缩小成了150和50,从上图也可看出效果。</p>
iconfont学习笔记
2017-11-04T07:06:38+00:00
https://blog.lisong.hn.cn/css/2017/11/04/iconfont学习笔记
<blockquote>
<p>iconfont是近年来前端领域兴起的一种新技术,在这之前,网页图标的展示大多数是用css sprite来实现,css sprite实现的图标在不同尺寸分辨率下有一定的的失真,而iconfont解决了此问题。</p>
</blockquote>
<h2 id="font-face">@font-face</h2>
<p>要使用iconfont,必须配合@font-face使用。@font-face是CSS3中的一个模块,他主要是把自己定义的Web字体嵌入到你的网页中。</p>
<h3 id="font-face的语法规则">@font-face的语法规则:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@font-face {
font-family: <YourWebFontName>;
src: <source> [<format>][,<source> [<format>]]*;
[font-weight: <weight>];
[font-style: <style>];
}
</code></pre></div></div>
<h3 id="font-face的属性解释">@font-face的属性解释:</h3>
<ul>
<li>font-family: <YourWebFontName> :自定义字库名称(一般设置为所引入的字库名),后续样式规则中则通过该名称来引用该字库。</YourWebFontName></li>
<li>src :设置字体的加载路径和格式,通过逗号分隔多个加载路径和格式</li>
<li>srouce :字体的加载路径,可以是绝对或相对URL。</li>
<li>format :字体的格式,主要用于浏览器识别,一般有以下几种——truetype,opentype,truetype-aat,embedded-opentype,avg等。</li>
<li>font-weight 和 font-style 和之前使用的是一致的。</li>
</ul>
<p>src属性后还有一个 local(font name) 字段,表示从用户系统中加载字体,失败后才加载webfont。</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">src</span><span class="o">:</span> <span class="nt">local</span><span class="o">(</span><span class="nt">font</span> <span class="nt">name</span><span class="o">),</span> <span class="nt">url</span><span class="o">(</span><span class="s1">"font_name.ttf"</span><span class="o">)</span>
</code></pre></div></div>
<h3 id="font-face的属性解释-1">@font-face的属性解释:</h3>
<ul>
<li>TrueType格式(.ttf):
Windows和Mac上常见的字体格式,是一种原始格式,因此它并没有为网页进行优化处理。
浏览器支持:IE9+,FireFox3.5+,Chrome4.0+,Safari3+,Opera10+,IOS Mobile Safari4.2+</li>
<li>OpenType格式(.otf):
以TrueType为基础,也是一种原始格式,但提供更多的功能。
浏览器支持:FireFox3.5+,Chrome4.0+,Safari3.1+,Opera10.0+,IOS Mobile Safari4.2+</li>
<li>Web Open Font格式(.woff):
针对网页进行特殊优化,因此是Web字体中最佳格式,它是一个开放的TrueType/OpenType的压缩版,同时支持元数据包的分离。
浏览器支持:IE9+, FireFox3.5+, Chrome6+, Safari3.6+,Opera11.1+</li>
<li>Embedded Open Type格式(.eot):
IE专用字体格式,可以从TrueType格式创建此格式字体。</li>
<li>SVG格式(.svg)
基于SVG字体渲染的格式。
浏览器支持:Chrome4+, Safari3.1+, Opera10.0+, IOS Mobile Safari3.2+</li>
</ul>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-04-iconfont学习笔记-1.png" alt="" /></p>
<h3 id="字符串对应值"><format>字符串对应值:</format></h3>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-04-iconfont学习笔记-2.png" alt="" /></p>
<p>图标字体的尅一使用阿里巴巴的<a href="http://www.iconfont.cn/">iconfont</a>和icomoon,制作推荐使用<a href="https://icomoon.io/app/#/select" rel="noopener" target="_blank">icomoon</a>。图标字体的使用主要有两种方式:html实体(兼容ie6),css伪类(ie8+)。</p>
<p>示例:</p>
<p>style:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@font-face</span> <span class="p">{</span>
<span class="nl">font-family</span><span class="p">:</span> <span class="s2">'icomoon'</span><span class="p">;</span>
<span class="nl">src</span><span class="p">:</span> <span class="sx">url('fonts/icomoon.eot')</span><span class="p">;</span><span class="c">/*ie9 兼容模式*/</span>
<span class="nl">src</span><span class="p">:</span> <span class="sx">url('fonts/icomoon.eot?#iefix')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'embedded-opentype'</span><span class="p">),</span>
<span class="sx">url('fonts/icomoon.ttf')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'truetype'</span><span class="p">),</span>
<span class="sx">url('fonts/icomoon.woff')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'woff'</span><span class="p">),</span>
<span class="sx">url('fonts/icomoon.svg')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'svg'</span><span class="p">);</span>
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="nl">font-style</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">[</span><span class="nt">class</span><span class="o">^=</span><span class="s1">"icon-"</span><span class="o">],</span> <span class="o">[</span><span class="nt">class</span><span class="o">*=</span><span class="s1">" icon-"</span><span class="o">]</span> <span class="p">{</span>
<span class="c">/* use !important to prevent issues with browser extensions that change fonts */</span>
<span class="nl">font-family</span><span class="p">:</span> <span class="s2">'icomoon'</span> <span class="cp">!important</span><span class="p">;</span>
<span class="nl">speak</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="nl">font-style</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="nl">font-variant</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="nl">text-transform</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="c">/* Better Font Rendering =========== */</span>
<span class="nl">-webkit-font-smoothing</span><span class="p">:</span> <span class="n">antialiased</span><span class="p">;</span>
<span class="nl">-moz-osx-font-smoothing</span><span class="p">:</span> <span class="n">grayscale</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.icon-home</span><span class="nd">:before</span> <span class="p">{</span>
<span class="nl">content</span><span class="p">:</span> <span class="s1">"\e900"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:?#iefix是用来解决ie6-8下不支持@font-face新规则的bug,ie6-8只支持一种url,通过使用?可以是ie6-8认为之后的都是查询字符串,避免加载失败;ie9 兼容模式主要是为了解决在ie9下,切换到低版本文档模式时防止ie使用woff格式的字体。</p>
<p>html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE>
<html>
<head>
<meta charset="utf-8">
<title>IcoMoon Demo</title>
<link rel="stylesheet" href="style.css"></head>
<body>
<!-- 使用css伪类 (ie8+)-->
<span class="icon-home"></span><br>
<!-- 使用字符实体 (ie6+)-->
<span style="font-family: icomoon">&#xe900;</span>
</body>
</html>
</code></pre></div></div>
<p>注意:在html文件中,字符实体以’$#x’开头,中间是编码,以’;’结尾,而在css的content中可以直接\后面跟着字符编码</p>
<p>在ie8下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-04-iconfont学习笔记-3.png" alt="" /></p>
<p>在ie7下结果:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-11-04-iconfont学习笔记-4.png" alt="" /></p>
<p>演示demo:<a href="http://lisong.hn.cn/blog-demo/icomoon-demo/demo.html" rel="noopener" target="_blank">http://lisong.hn.cn/blog-demo/icomoon-demo/demo.html</a></p>
<h2 id="彩色字体图标">彩色字体图标</h2>
<p>iconfont和icomoon都能生成彩色字体图标,不过两者的实现方式稍有不同,iconfont使用的是svg形式,只支持ie9+。而icomoon使用的依然是字体形式,通过多个字体拼凑成最终的图标,字符实体的形式依然可以支持i6,下面是icomoon多彩字体的示例代码。</p>
<p>html:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!doctype html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><title></span>IcoMoon 多彩字体Demo<span class="nt"></title></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">href=</span><span class="s">"style.css"</span><span class="nt">></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="c"><!-- 实体形式 --></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"icon-basketball"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"path1"</span><span class="nt">></span><span class="ni">&#xe900;</span><span class="nt"></span><span</span> <span class="na">class=</span><span class="s">"path2"</span><span class="nt">></span><span class="ni">&#xe901;</span><span class="nt"></span></span>
<span class="nt"></span></span>
<span class="nt"><br></span>
<span class="c"><!-- 伪类形式 --></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"icon-basketball-1"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">class=</span><span class="s">"path1"</span><span class="nt">></span><span</span> <span class="na">class=</span><span class="s">"path2"</span><span class="nt">></span></span>
<span class="nt"></span></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>style:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@font-face</span> <span class="p">{</span>
<span class="nl">font-family</span><span class="p">:</span> <span class="s2">'icomoon'</span><span class="p">;</span>
<span class="nl">src</span><span class="p">:</span> <span class="sx">url('fonts/icomoon.eot')</span><span class="p">;</span>
<span class="nl">src</span><span class="p">:</span> <span class="sx">url('fonts/icomoon.eot?g1shvp#iefix')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'embedded-opentype'</span><span class="p">),</span>
<span class="sx">url('fonts/icomoon.ttf')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'truetype'</span><span class="p">),</span>
<span class="sx">url('fonts/icomoon.woff')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'woff'</span><span class="p">),</span>
<span class="sx">url('fonts/icomoon.svg')</span> <span class="n">format</span><span class="p">(</span><span class="s2">'svg'</span><span class="p">);</span>
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="nl">font-style</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">[</span><span class="nt">class</span><span class="o">^=</span><span class="s1">"icon-"</span><span class="o">],</span> <span class="o">[</span><span class="nt">class</span><span class="o">*=</span><span class="s1">" icon-"</span><span class="o">]</span> <span class="p">{</span>
<span class="c">/* use !important to prevent issues with browser extensions that change fonts */</span>
<span class="nl">font-family</span><span class="p">:</span> <span class="s2">'icomoon'</span> <span class="cp">!important</span><span class="p">;</span>
<span class="nl">speak</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="nl">font-style</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="nl">font-variant</span><span class="p">:</span> <span class="nb">normal</span><span class="p">;</span>
<span class="nl">text-transform</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="c">/* Better Font Rendering =========== */</span>
<span class="nl">-webkit-font-smoothing</span><span class="p">:</span> <span class="n">antialiased</span><span class="p">;</span>
<span class="nl">-moz-osx-font-smoothing</span><span class="p">:</span> <span class="n">grayscale</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.icon-basketball</span> <span class="nc">.path1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="nb">rgb</span><span class="p">(</span><span class="m">255</span><span class="p">,</span> <span class="m">172</span><span class="p">,</span> <span class="m">82</span><span class="p">);</span>
<span class="p">}</span>
<span class="nc">.icon-basketball</span> <span class="nc">.path2</span> <span class="p">{</span>
<span class="nl">margin-left</span><span class="p">:</span> <span class="m">-1em</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="nb">rgb</span><span class="p">(</span><span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">);</span>
<span class="p">}</span>
<span class="nc">.icon-basketball-1</span> <span class="nc">.path1</span><span class="nd">:before</span> <span class="p">{</span>
<span class="nl">content</span><span class="p">:</span> <span class="s1">"\e900"</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="nb">rgb</span><span class="p">(</span><span class="m">255</span><span class="p">,</span> <span class="m">172</span><span class="p">,</span> <span class="m">82</span><span class="p">);</span>
<span class="p">}</span>
<span class="nc">.icon-basketball-1</span> <span class="nc">.path2</span><span class="nd">:before</span> <span class="p">{</span>
<span class="nl">content</span><span class="p">:</span> <span class="s1">"\e901"</span><span class="p">;</span>
<span class="nl">margin-left</span><span class="p">:</span> <span class="m">-1em</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="nb">rgb</span><span class="p">(</span><span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">,</span> <span class="m">0</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>icomoon demo示例:</p>
<p><a href="http://lisong.hn.cn/blog-demo/icomoon-color-icon/demo.html">http://lisong.hn.cn/blog-demo/icomoon-color-icon/demo.html</a></p>
<p>iconfont demo示例:</p>
<p><a href="http://lisong.hn.cn/blog-demo/iconfont-demo/demo.html">http://lisong.hn.cn/blog-demo/iconfont-demo/demo.html</a></p>
<h2 id="浏览器模式和文档模式的区别">“浏览器模式”和“文档模式”的区别</h2>
<p>“浏览器模式”用于切换IE针对该网页的默认文档模式、对不同版本浏览器的条件备注解析、发送给网站服务器的用户代理(User-Agent)字符串的值。网站可以根据浏览器返回的不同用户代理字符串判断浏览器的版本和安装的功能,这样就可以向不同的浏览器返回不同的页面内容。“文档模式”用于指定IE的页面排版引擎(Trident)以哪个版本的方式来解析并渲染网页代码。切换文档模式会导致网页被刷新,但不会更改用户代理字符串中的版本号,也不会从服务器重新下载网页。</p>
https工作原理
2017-10-21T18:35:44+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2017/10/21/https工作原理
<blockquote>
<p>HTTPS在传输数据之前需要客户端(浏览器)与服务端(网站)之间进行一次握手,在握手过程中将确立双方加密传输数据的密码信息。TLS/SSL协议使用了非对称加密,对称加密以及HASH算法。</p>
</blockquote>
<h2 id="握手过程的简单描述如下">握手过程的简单描述如下:</h2>
<ol>
<li>浏览器将自己支持的一套加密规则发送给网站。</li>
<li>网站从中选出一组加密算法与HASH算法,并将自己的身份信息以证书的形式发回给浏览器。证书里面包含了网站地址,加密公钥,以及证书的颁发机构等信息。</li>
<li>获得网站证书之后浏览器要做以下工作:
<ul>
<li>a) 验证证书的合法性(颁发证书的机构是否合法,证书中包含的网站地址是否与正在访问的地址一致等),如果证书受信任,则浏览器栏里面会显示一个小锁头,否则会给出证书不受信的提示。</li>
<li>b) 如果证书受信任,或者是用户接受了不受信的证书,浏览器会生成一串随机数的密码,并用证书中提供的公钥加密。</li>
<li>c) 使用约定好的HASH计算握手消息,并使用生成的随机数对消息进行加密,最后将之前生成的所有信息发送给网站。</li>
</ul>
</li>
<li>网站接收浏览器发来的数据之后要做以下的操作:
<ul>
<li>a) 使用自己的私钥将信息解密取出密码,使用密码解密浏览器发来的握手消息,并验证HASH是否与浏览器发来的一致。</li>
<li>b) 使用密码加密一段握手消息,发送给浏览器。</li>
</ul>
</li>
<li>浏览器解密并计算握手消息的HASH,如果与服务端发来的HASH一致,此时握手过程结束,之后所有的通信数据将由之前浏览器生成的随机密码并利用对称加密算法进行加密。</li>
</ol>
<p>这里浏览器与网站互相发送加密的握手消息并验证,目的是为了保证双方都获得了一致的密码,并且可以正常的加密解密数据,为后续真正数据的传输做一次测试。另外,HTTPS一般使用的加密与HASH算法如下:</p>
<ul>
<li>非对称加密算法:RSA,DSA/DSS</li>
<li>对称加密算法:AES,RC4,3DES</li>
<li>HASH算法:MD5,SHA1,SHA256</li>
</ul>
<p>其中非对称加密算法用于在握手过程中加密生成的密码,对称加密算法用于对真正传输的数据进行加密,而HASH算法用于验证数据的完整性。由于浏览器生成的密码是整个数据加密的关键,因此在传输的时候使用了非对称加密算法对其加密。非对称加密算法会生成公钥和私钥,公钥只能用于加密数据,因此可以随意传输,而网站的私钥用于对数据进行解密,所以网站都会非常小心的保管自己的私钥,防止泄漏。</p>
移动端适配
2017-10-14T13:46:37+00:00
https://blog.lisong.hn.cn/%E7%A7%BB%E5%8A%A8%E7%AB%AF/2017/10/14/移动端适配
<blockquote>
<p>随着硬件技术的发展,移动端手机的屏幕分辨率越来越多,为了处理屏幕碎片化问题和方便移动端界面的开发,当前两个主流移动端操作系统(Android,IOS)都抽象出了一套屏幕适配方案,本文章主要讲解两套适配方案的原理。</p>
</blockquote>
<h2 id="移动开发中的一些概念">移动开发中的一些概念</h2>
<p><strong>屏幕尺寸相关的单位和术语</strong>:</p>
<ul>
<li><strong>pt(point)</strong>:磅,一个标准的物理绝对长度单位,大小为1/72英寸。主要用于印刷与平面设计。1inch = 2.54cm=72pt。</li>
<li><strong>px(pixel)</strong>:物理像素,组成屏幕图像的最小点,一个相对大小单位。同尺寸屏幕中像素越小越多,代表分辨率越高,反之越低。</li>
<li><strong>屏幕尺寸(Screen Size)</strong>:屏幕物理尺寸,指屏幕对角线长度,而不是屏幕宽度或高度。</li>
<li><strong>分辨率(Resolution)</strong>:屏幕拥有像素的总数以及屏幕水平(宽)和垂直(高)方向的像素数量。</li>
<li><strong>ppi(pixels per inch)</strong>:屏幕密度,指每英寸所拥有的像素数/每英寸像素。ppi数值越高,即代表显示屏能够以越高的密度显示图像。显示的密度越高,拟真度就越高。当你拿的手机距离你约25-30厘米,如果手机ppi达到300以上,你的眼睛将无法分辨出像素点。这就是苹果提出的视网膜屏幕。</li>
<li><strong>dpi(dots per inch)</strong>:印刷计数单位,指每英寸所能印刷出来的网点数。衡量打印机打印精度的主要参数之一,值越大,表明打印机的打印精度越高。电脑图片为72dpi 。但印刷图片dpi参数最好是300dpi以上。如果冲洗5x7英寸的照片,dpi是300,照片需达到(5x300)x(7x300)= 1500 x 2100像素。photoshop中的分辨率设置指的其实就是dpi</li>
</ul>
<p><strong>换算公式</strong>:</p>
<p>1pt = (ppi / 72) x px</p>
<p>在物理屏上:ppi=dpi</p>
<p>PPI = √(X^2+Y^2)/ Z</p>
<h2 id="安卓开发中的适配方案">安卓开发中的适配方案</h2>
<p>为了方便程安卓序员的开发,安卓操作系统将手机屏幕分成了不同的等级。</p>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-10-14-移动端适配-1.png" alt="" /></p>
<p><strong>Andorid手机相关的单位和标准</strong>:</p>
<ul>
<li>dip(Device Independent Pixels):设备独立像素单位。 Android开发虚拟单位。多用于Android示例计数单位。</li>
<li>dp:android开发中的布局长度单位,和ios中的pt概念一样,是一个虚拟单位</li>
<li>sp:和dp一样,只不过是用来设定字体大小的,sp设定字体大小可以随用户的缩放而改变大小,在每英寸160点的显示器上,当文字大小为100%时,1sp = 1px。</li>
</ul>
<p><strong>转换公式</strong>:</p>
<p>dp = (ppi/160) x px</p>
<p>dip = dp</p>
<p>从上图中可以看出,逻辑密度和真实密度是有一定的差距的,设备的真实密度通过某个范围归类到某一个逻辑密度,从而划分成不同的密度等级。</p>
<p>不同等级密度中,1dp所代表的理想物理尺寸是一致的,例如上图的Mdpi中:1dp = 320/160/320 = 1/160inch,XHdpi中:1dp = 720/320/360 = 1/160inch。</p>
<p>由于设备的真实密度与逻辑有一定的差距,所以1dp多代表的物理尺寸会有稍微的区别,不过大体上接近某一个值,公式为:1dp = 设备分辨率/真实密度/逻辑分辨率。</p>
<p>在相同密度等级的设备,虽然1dp所代表的物理像素的个数相等,但由于真实密度有区别,所以相等的像素个数所占据的物理尺寸是有差别的。</p>
<h2 id="ios开发中的适配方案">IOS开发中的适配方案</h2>
<p>IOS的适配方案和安卓的类似,都是通过虚拟单位结合转换比去实现。</p>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-10-14-移动端适配-2.png" alt="" /></p>
<p><strong>IOS手机相关的单位和标准</strong>:</p>
<ul>
<li>pt:ios中的虚拟单位,类似安卓中的dp</li>
</ul>
<p>从上图中可以看出,ios中的转换比是以ppi=163的密度来计算的,在ios中,如果屏幕最终渲染的大小和屏幕分辨率的大小一致,那么1pt所代表的物理尺寸=1/163inch。在上图中除了6+,其他设备的1dp均等于1/163英寸。</p>
<p>6+手机因为特殊的PPI,如果按照正常的计算方式,其比例因素将不等于整数,为了方便移动端开发,6+手机采用了虚拟放大技术,将屏幕分辨率虚拟成(1242x2208),使其设备像素比刚好等于3。在最终的渲染中,通过缩小虚拟分辨率(1242x2208)使屏幕的最终渲染结果等于物理分辨率(1080x1920)。</p>
<p>在6+中,1dp不在等于1/163英寸,而是 = 1080/401/414英寸,略大于1/163。</p>
<h2 id="web开发中的适配方案">WEB开发中的适配方案</h2>
<p>在web网页开发中,也有专门用于屏幕适配的viewport标签。css中的px单位也是一个虚拟单位,和物理像素单位不是一个概率。</p>
<p>viewport标签content参数:</p>
<ul>
<li>width:用于控制布局viewport的大小</li>
<li>initial-scale:用于控制初始度量viewport的大小,计算规则=设备的逻辑分辨率宽/initial-scale</li>
<li>minimum-scale:用于控制最小度量viewport的大小</li>
<li>maximum-scale:用于控制最大度量viewport的大小</li>
<li>user-scale:是否允许用户缩放页面</li>
</ul>
<p>其中布局viewport可以使用document.body.clientWidth来获取,度量viewport可以使用window.innerWidth来获取(在某些浏览器上,如果度量视口小于元素宽度,则 window.innerWidth 将为元素的宽度,不等于度量视口的宽度),window.outerWidth可以获取到设备的逻辑分辨率宽,此时的px对应于安卓的dp或ios的pt。</p>
<p>移动端页面,如果没有设置viewport标签,默认会有一个980px的布局视口,而默认度量视口没有固定值,只有一个默认最大度量视口(即使设置 scale,最多也只能缩放到该大小),不同设备的默认最大度量视口不一致。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
body{
margin:0;
padding-top: 0;
}
#d1{
width: 1800px;
height: 100px;
background: red;
}
</style>
</head>
<body>
<div id='d1'></div>
</body>
<script type="text/javascript">
</script>
</html>
</code></pre></div></div>
<p>iphone5下最大度量视口为1280px,iphone6下最大度量视口为1600px:</p>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-10-14-移动端适配-3.png" alt="" /></p>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-10-14-移动端适配-4.png" alt="" /></p>
<p>如果只设置了布局视口,则度量视口会根据页面元素的宽度设置一个合适的值:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=1000">
<title>Document</title>
<style type="text/css">
body{
margin:0;
padding-top: 0;
}
#d1{
width: 1300px;
height: 100px;
background: red;
}
</style>
</head>
<body>
<div id='d1'></div>
</body>
<script type="text/javascript">
</script>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-10-14-移动端适配-7.png" alt="" /></p>
<p>如果只设置了度量视口,则布局视口将等于度量视口:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="initial-scale=0.3">
<title>Document</title>
<style type="text/css">
body{
margin:0;
padding-top: 0;
}
#d1{
width: 750px;
height: 100px;
background: red;
}
</style>
</head>
<body>
<div id='d1'></div>
</body>
<script type="text/javascript">
</script>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-10-14-移动端适配-8.png" alt="" /></p>
<p>如果度量视口小于布局视口将产生滚动条:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=750,initial-scale=0.8">
<title>Document</title>
<style type="text/css">
body{
margin:0;
padding-top: 0;
}
#d1{
width: 750px;
height: 100px;
background: red;
}
</style>
</head>
<body>
<div id='d1'></div>
</body>
<script type="text/javascript">
</script>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-10-14-移动端适配-5.png" alt="" /></p>
<p>如果设置的度量视口宽度大于布局视口的宽度,则布局视口会自动设置成度量视口的宽度:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><meta name="viewport" content="width=750,initial-scale=0.2">
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-10-14-移动端适配-6.png" alt="" /></p>
<p><strong>最后在来说一下一个已经被安卓废弃的viewport属性target-densitydpi</strong>:</p>
<p>target-densitydpi表示目标设备的密度等级,作用是决定css中的1px代表多少物理像素,target-densitydpi 值可以为一个数值或 high-dpi 、 medium-dpi、 low-dpi、 device-dpi 这几个字符串中的一个特别说明的是,当 target-densitydpi=device-dpi 时, css中的1px会等于物理像素中的1px。因为这个属性只有安卓支持(andorid4.0以下的手机不支持viewport的width属性,可以用target-densitydpi代替),并且安卓已经决定要废弃 target-densitydpi 这个属性了,尽量避免使用这个属性。</p>
理解css小数点像素
2017-09-16T07:55:14+00:00
https://blog.lisong.hn.cn/css/2017/09/16/理解css小数点像素
<blockquote>
<p>css中不存在真正的小数点像素,不同的浏览器对小数点有不同的解析,现代浏览器大多数会使用四舍五入以及相邻元素互补的方式去处理。解析与处理只是针对渲染级别,其真正的值在其DOM树中并没有改变,所以别去相信浏览器调试器所展示的小数点值。</p>
</blockquote>
<h2 id="四舍五入">四舍五入:</h2>
<p>大多数浏览器渲染页面的时候,如果遇到小数点像素,将会四舍五入成整数,然后再去真正的渲染,而旧版ie只是简单的去除后面的小数。</p>
<p>示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<title>test</title>
<style type="text/css">
.div1{
width: 300px;
height: 200px;
background: red;
overflow: auto;
}
.div2{
float: left;
width: 299.5px;
height: 100px;
background: #999;
}
</style>
</head>
<body>
<div class="div1">
<div class="div2"></div>
</div>
</body>
</html>
</code></pre></div></div>
<p>结果:
<img src="https://wanls4583.github.io/images/posts/CSS/2017-09-16-理解css小数点像素-1.png" alt="" />
可以看出,299.5px和外部容器一样宽,说明299.5被渲染成了300px。</p>
<h2 id="相邻元素互补">相邻元素互补:</h2>
<p>示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<title>test</title>
<style type="text/css">
.div1{
width: 300px;
height: 200px;
background: red;
overflow: auto;
}
.div2{
float: left;
width: 99.3px;
height: 100px;
background: #999;
}
.div3{
float: left;
width: 99.4px;
height: 100px;
background: #666;
}
.div4{
float: left;
width: 100.8px;
height: 100px;
background: #000;
}
</style>
</head>
<body>
<div class="div1">
<div class="div2"></div>
<div class="div3"></div>
<div class="div4"></div>
</div>
</body>
</html>
</code></pre></div></div>
<p>结果:
<img src="https://wanls4583.github.io/images/posts/CSS/2017-09-16-理解css小数点像素-2.png" alt="" />
该图是火狐浏览器里运行的结果,从图中可以看出,三个div的渲染总宽度为300,但是这和上面的四舍五入法是有出入,因为99.3->99,99.4->99,100.8->100,最终结果应该是99+99+101=299。这就涉及到浏览器处理小数点像素的一些规则,具体对应到该示例的步骤如下:</p>
<p>1.div2宽度99.3px渲染成99px,多出0.3px留给右边相邻的元素;</p>
<p>2.div3宽度99.4px+0.3px=99.7px,向右边相邻元素(如果有)借0.3px,99.7px+0.3px=100px,最终div3的渲染像素为100px;</p>
<p>3.div4宽度100.8px-0.3px=100.5px,向右边相邻元素借0.5px,因为右边已经没有相邻元素,直接四舍五入100.5px->101px;</p>
<p>所以,最终结果是99px+100px+101px=300px,正好符合上面的结果。</p>
<p>然而在某些浏览器中最后一个元素的四舍五入会有一点不同,其必须满6才进10,而不是满5进10,例如以下截图是在360浏览器下的结果:
<img src="https://wanls4583.github.io/images/posts/CSS/2017-09-16-理解css小数点像素-3.png" alt="" />
因为最后一个元素div4处理后的像素为100.5px,0.5不满6,所以舍如,最终为100px,最终结果为99px+100px+100px=299px。</p>
<p>如果将div4的宽度设置成100.9px,情况就变成预期结果了:
<img src="https://wanls4583.github.io/images/posts/CSS/2017-09-16-理解css小数点像素-4.png" alt="" /></p>
css3动画事件
2017-08-20T03:59:41+00:00
https://blog.lisong.hn.cn/css/2017/08/20/css3动画事件
<blockquote>
<p>css3动画事件包括transitionend事件和animationend事件,transitionend和animationend是w3c标准的写法,而多数浏览器在w3c标准前已经有了对应的私有写法(多数浏览器同时支持私有和标准写法,部分旧版浏览器只支持私有写法)。</p>
</blockquote>
<p>当浏览器同时支持标准和私有写法时,如果某个元素同时监听了私有写法事件和标准写法事件,则浏览器将只执行标准写法的回调。当然,也可以只监听标准写法事件或者私有写法事件,前提是你明确知道事件是否被浏览器支持,否则应该做兼容</p>
<p>示例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"utf-8"</span><span class="nt">></span>
<span class="nt"><title></span>菜鸟教程(runoob.com)<span class="nt"></title></span>
<span class="nt"><style></span>
<span class="nf">#myDIV</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">-webkit-transition</span><span class="p">:</span> <span class="n">width</span> <span class="m">2s</span><span class="p">;</span>
<span class="c">/* For Safari 3.1 to 6.0 */</span>
<span class="nl">transition</span><span class="p">:</span> <span class="n">width</span> <span class="m">2s</span><span class="p">;</span>
<span class="p">}</span>
<span class="nf">#myDIV</span><span class="nd">:hover</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">400px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><script></span>
<span class="c1">// Safari 3.1 到 6.0 版本代码</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">myDIV</span><span class="dl">"</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">webkitTransitionEnd</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">webkitTransitionEnd1</span><span class="dl">'</span><span class="p">)</span>
<span class="p">});</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">myDIV</span><span class="dl">"</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">webkitTransitionEnd</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">webkitTransitionEnd2</span><span class="dl">'</span><span class="p">)</span>
<span class="p">});</span>
<span class="c1">// 标准语法</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">myDIV</span><span class="dl">"</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">transitionend</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">transitionend1</span><span class="dl">'</span><span class="p">)</span>
<span class="p">});</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">myDIV</span><span class="dl">"</span><span class="p">).</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">"</span><span class="s2">transitionend</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">transitionend2</span><span class="dl">'</span><span class="p">);</span>
<span class="p">});</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>多数现代webkit浏览器将只打印transitionend1和transitionend2,虽然其也支持webkitTransitionEnd。</p>
<p>兼容性处理:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">body</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">body</span> <span class="o">||</span> <span class="nb">document</span><span class="p">.</span><span class="nx">documentElement</span><span class="p">,</span>
<span class="nx">style</span> <span class="o">=</span> <span class="nx">body</span><span class="p">.</span><span class="nx">style</span><span class="p">,</span>
<span class="nx">transition</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">transition</span><span class="dl">"</span><span class="p">,</span>
<span class="nx">transitionEnd</span><span class="p">,</span>
<span class="nx">animationEnd</span><span class="p">,</span>
<span class="nx">setStyleAttribute</span><span class="p">,</span>
<span class="nx">vendorPrefix</span><span class="p">;</span>
<span class="nx">transition</span> <span class="o">=</span> <span class="nx">transition</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">).</span><span class="nx">toUpperCase</span><span class="p">()</span> <span class="o">+</span> <span class="nx">transition</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">vendorPrefix</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span> <span class="c1">//现在的opera也是webkit</span>
<span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
<span class="nx">vendor</span> <span class="o">=</span> <span class="p">[</span><span class="dl">"</span><span class="s2">Moz</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">Webkit</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">Khtml</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">O</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">ms</span><span class="dl">"</span><span class="p">];</span>
<span class="k">while</span> <span class="p">(</span><span class="nx">i</span> <span class="o"><</span> <span class="nx">vendor</span><span class="p">.</span><span class="nx">length</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">style</span><span class="p">[</span><span class="nx">vendor</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">+</span> <span class="nx">transition</span><span class="p">]</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">vendor</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="p">}</span>
<span class="nx">i</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">})();</span>
<span class="nx">transitionEnd</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">transEndEventNames</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">WebkitTransition</span><span class="p">:</span> <span class="dl">'</span><span class="s1">webkitTransitionEnd</span><span class="dl">'</span><span class="p">,</span>
<span class="na">MozTransition</span><span class="p">:</span> <span class="dl">'</span><span class="s1">transitionend</span><span class="dl">'</span><span class="p">,</span>
<span class="na">OTransition</span><span class="p">:</span> <span class="dl">'</span><span class="s1">oTransitionEnd otransitionend</span><span class="dl">'</span><span class="p">,</span>
<span class="na">transition</span><span class="p">:</span> <span class="dl">'</span><span class="s1">transitionend</span><span class="dl">'</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">name</span> <span class="k">in</span> <span class="nx">transEndEventNames</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">style</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">transEndEventNames</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})();</span>
<span class="nx">animationEnd</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">animEndEventNames</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">WebkitAnimation</span><span class="p">:</span> <span class="dl">'</span><span class="s1">webkitAnimationEnd</span><span class="dl">'</span><span class="p">,</span>
<span class="na">animation</span><span class="p">:</span> <span class="dl">'</span><span class="s1">animationend</span><span class="dl">'</span>
<span class="p">}</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">name</span> <span class="k">in</span> <span class="nx">animEndEventNames</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="nx">style</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">string</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">animEndEventNames</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})();</span>
<span class="nx">setStyleAttribute</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">elem</span><span class="p">,</span> <span class="nx">val</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">val</span><span class="p">)</span> <span class="o">===</span> <span class="dl">"</span><span class="s2">[object Object]</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">name</span> <span class="k">in</span> <span class="nx">val</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="sr">/^transition|animation|transform/</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="nx">name</span><span class="p">))</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">styleName</span> <span class="o">=</span> <span class="nx">name</span><span class="p">.</span><span class="nx">charAt</span><span class="p">(</span><span class="mi">0</span><span class="p">).</span><span class="nx">toUpperCase</span><span class="p">()</span> <span class="o">+</span> <span class="nx">name</span><span class="p">.</span><span class="nx">substr</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">elem</span><span class="p">.</span><span class="nx">style</span><span class="p">[</span><span class="nx">vendorPrefix</span> <span class="o">+</span> <span class="nx">styleName</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span><span class="p">[</span><span class="nx">name</span><span class="p">];</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">elem</span><span class="p">.</span><span class="nx">style</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span> <span class="o">=</span> <span class="nx">val</span><span class="p">[</span><span class="nx">name</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">css3Hack</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">transitionEnd</span><span class="p">:</span> <span class="nx">transitionEnd</span><span class="p">,</span>
<span class="na">animationEnd</span><span class="p">:</span> <span class="nx">animationEnd</span><span class="p">,</span>
<span class="na">setStyleAttribute</span><span class="p">:</span> <span class="nx">setStyleAttribute</span>
<span class="p">}</span>
<span class="p">})()</span>
</code></pre></div></div>
sublime 常用快捷键
2017-08-05T17:52:20+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/08/05/sublime 常用快捷键
<h2 id="常用命令">常用命令</h2>
<h3 id="选择类">选择类</h3>
<p>Ctrl+D 选中光标所占的文本,继续操作则会选中下一个相同的文本。</p>
<p>ctrl+shift+d 如果你已经选中了文本,它会复制你的选中项。否则,把光标放在行上,会复制整行。</p>
<p>Alt+- 光标回到上一次的位置,可连续使用</p>
<p>Alt+F3 选中文本按下快捷键,即可一次性选择全部的相同文本进行同时编辑。举个栗子:快速选中并更改所有相同的变量名、函数名等。</p>
<p>Ctrl+L 选中整行,继续操作则继续选择下一行,效果和 Shift+↓ 效果一样。</p>
<p>Ctrl+Shift+L 先选中多行,再按下快捷键,会在每行行尾插入光标,即可同时编辑这些行。</p>
<p>Ctrl+Shift+M 选择括号内的内容(继续选择父括号)。举个栗子:快速选中删除函数中的代码,重写函数体代码或重写括号内里的内容。</p>
<p>Ctrl+M 光标移动至括号内结束或开始的位置。</p>
<p>Ctrl+Enter 在下一行插入新行。举个栗子:即使光标不在行尾,也能快速向下插入一行。</p>
<p>Ctrl+Shift+Enter 在上一行插入新行。举个栗子:即使光标不在行首,也能快速向上插入一行。</p>
<p>Ctrl+Shift+[ 选中代码,按下快捷键,折叠代码。</p>
<p>Ctrl+Shift+] 选中代码,按下快捷键,展开代码。</p>
<p>Ctrl+K+0 展开所有折叠代码。</p>
<p>Ctril+k+1 折叠所有代码,1为折叠层数,可以大于1</p>
<p>Ctrl+← 向左单位性地移动光标,快速移动光标。</p>
<p>Ctrl+→ 向右单位性地移动光标,快速移动光标。</p>
<p>Shift+↑ 向上选中多行。</p>
<p>Shift+↓ 向下选中多行。</p>
<p>Shift+← 向左选中文本。</p>
<p>Shift+→ 向右选中文本。</p>
<p>Ctrl+Shift+← 向左单位性地选中文本。</p>
<p>Ctrl+Shift+→ 向右单位性地选中文本。</p>
<p>Ctrl+Shift+↑ 将光标所在行和上一行代码互换(将光标所在行插入到上一行之前)。</p>
<p>Ctrl+Shift+↓ 将光标所在行和下一行代码互换(将光标所在行插入到下一行之后)。</p>
<p>Ctrl+shift+a 如果你把光标放在文本间再按下上面的键将选择文本。但是再次按下它,将选择父容器,再按,将选择父容器的父容器。(需要Emmet插件)</p>
<h3 id="编辑类">编辑类</h3>
<p>Ctrl+J 合并选中的多行代码为一行。举个栗子:将多行格式的CSS属性合并为一行。</p>
<p>Tab 向右缩进。</p>
<p>Shift+Tab 向左缩进。</p>
<p>ctrl+[或] 增加和减少缩进</p>
<p>Ctrl+K+K 从光标处开始删除代码至行尾。</p>
<p>Ctrl+Shift+K 删除整行。</p>
<p>Ctrl+/ 注释单行。</p>
<p>Ctrl+Shift+/ 注释多行。</p>
<p>Ctrl+K+U 转换大写。</p>
<p>Ctrl+K+L 转换小写。</p>
<p>Ctrl+Z 撤销。</p>
<p>Ctrl+Y 恢复撤销。</p>
<p>Ctrl+Shift+D 快速复制光标所在的一整行,并复制到该行之前。</p>
<h3 id="搜索类">搜索类</h3>
<p>Ctrl+F 打开底部搜索框,查找关键字。</p>
<p>Ctrl+shift+F 在文件夹内查找,与普通编辑器不同的地方是sublime允许添加多个文件夹进行查找,略高端,未研究。</p>
<p>Ctrl+P 打开搜索框。举个栗子:</p>
<ul>
<li>输入当前项目中的文件名,快速搜索文件</li>
<li>输入@和关键字,查找文件中函数名</li>
<li>输入:和数字,跳转到文件中该行代码</li>
<li>输入#和关键字,查找变量名</li>
</ul>
<p>Ctrl+R 查找文件中函数名</p>
<p>Ctrl+G 跳转到文件中指定行</p>
<h3 id="显示类">显示类</h3>
<p>Ctrl+Tab 按文件浏览过的顺序,切换当前窗口的标签页。</p>
<p>Ctrl+PageDown 向左切换当前窗口的标签页。</p>
<p>Ctrl+PageUp 向右切换当前窗口的标签页。</p>
<p>Alt+Shift+1 窗口分屏,恢复默认1屏(非小键盘的数字)</p>
<p>Alt+Shift+2 左右分屏-2列</p>
<p>Alt+Shift+3 左右分屏-3列</p>
<p>Alt+Shift+4 左右分屏-4列</p>
<p>Alt+Shift+5 等分4屏</p>
<p>Alt+Shift+8 垂直分屏-2屏</p>
<p>Alt+Shift+9 垂直分屏-3屏</p>
<p>Ctrl+K+B 开启/关闭侧边栏。</p>
<h2 id="注意事项">注意事项</h2>
<ol>
<li>鼠标选中单词后再 Ctrl+D 只能进行模糊匹配,如果只是输入符定位到该单词上,再 Ctrl+D 则能进行精确匹配。</li>
</ol>
Javascript设计模式(责任链模式)
2017-07-23T08:21:52+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/23/Javascript设计模式(责任链模式)
<blockquote>
<p>在责任链模式中:发送者知道链中的第一个接受者;它向这个接受者发出请求,每一个接受者都对请求进行分析,要么处理它,要么往下传递;每一个接受者知道的其他对象只有一个,即它的下家对象;如果没有任何接受者处理请求,那么请求将从链上离开,不同的实现对此有不同的反应。</p>
</blockquote>
<p>实例:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//任务发送者</span>
<span class="kd">var</span> <span class="nx">Assign</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">task</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">task</span> <span class="o">=</span> <span class="nx">task</span> <span class="p">;</span>
<span class="p">};</span>
<span class="c1">//任务接受者</span>
<span class="kd">var</span> <span class="nx">Reciever</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">cando</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">cando</span> <span class="o">=</span> <span class="nx">cando</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Reciever</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">constructor</span><span class="p">:</span> <span class="nx">Reciever</span><span class="p">,</span>
<span class="na">execute</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">assign</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">cando</span> <span class="o">==</span> <span class="nx">assign</span><span class="p">.</span><span class="nx">task</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">name</span><span class="o">+</span><span class="dl">'</span><span class="s1">负责</span><span class="dl">'</span><span class="o">+</span><span class="nx">assign</span><span class="p">.</span><span class="nx">task</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">successor</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">successor</span><span class="p">.</span><span class="nx">execute</span><span class="p">(</span><span class="nx">assign</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="c1">//设置责任链的配置函数</span>
<span class="na">setSuccessor</span><span class="p">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">successor</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">successor</span> <span class="o">=</span> <span class="nx">successor</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">successor</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">assign</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Assign</span><span class="p">(</span><span class="dl">'</span><span class="s1">js</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">rec1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Reciever</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">java</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">rec2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Reciever</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工2</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">ui</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">rec3</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Reciever</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工3</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">js</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">rec4</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Reciever</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工4</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">c++</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">rec1</span><span class="p">.</span><span class="nx">setSuccessor</span><span class="p">(</span><span class="nx">rec2</span><span class="p">).</span><span class="nx">setSuccessor</span><span class="p">(</span><span class="nx">rec3</span><span class="p">).</span><span class="nx">setSuccessor</span><span class="p">(</span><span class="nx">rec4</span><span class="p">);</span>
<span class="nx">rec1</span><span class="p">.</span><span class="nx">execute</span><span class="p">(</span><span class="nx">assign</span><span class="p">);</span>
</code></pre></div></div>
Javascript设计模式(命令模式)
2017-07-23T06:42:38+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/23/Javascript设计模式(命令模式)
<blockquote>
<p>“行为请求者”与“行为实现者”通常呈现一种“紧耦合”。但在某些场合,比如要对行为进行“记录、撤销/重做、事务”等处理,这种无法抵御变化的紧耦合是不合适的。在这种情况下,如何将“行为请求者”与“行为实现者”解耦?将一组行为抽象为对象,实现二者之间的松耦合。这就是命令模式(Command Pattern)。</p>
</blockquote>
<p>实例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
#div1{
position: fixed;left:50%;top:50%;width: 50px;height: 50px;background: red;
}
</style>
<script type="text/javascript">
//调用者,向上命令
var MoveUp = function(reciever){
this.reciever = reciever;
};
MoveUp.prototype.execute = function(){
this.reciever.move(0,-10);
}
MoveUp.prototype.undo = function(){
this.reciever.move(0,10);
}
//调用者,向下命令
var MoveDown = function(reciever){
this.reciever = reciever;
};
MoveDown.prototype.execute = function(){
this.reciever.move(0,10);
}
MoveDown.prototype.undo = function(){
this.reciever.move(0,-10);
}
//调用者,向左命令
var MoveLeft = function(reciever){
this.reciever = reciever;
};
MoveLeft.prototype.execute = function(){
this.reciever.move(-10,0);
}
MoveLeft.prototype.undo = function(){
this.reciever.move(10,0);
}
//调用者,向右命令
var MoveRight = function(reciever){
this.reciever = reciever;
};
MoveRight.prototype.execute = function(){
this.reciever.move(10,0);
}
MoveRight.prototype.undo = function(){
this.reciever.move(-10,0);
}
//接受者,真正执行操作的类
var Reciever = function(){};
Reciever.prototype.move = function(left,top){
var div = document.getElementById('div1');
var left = div.offsetLeft+left;
var top = div.offsetTop+top;
div.style.setProperty("left",left+"px");
div.style.setProperty("top",top+"px");
}
//装饰者,添加记录操作的行为
var UndoDercorator = function(command){
this.command = command;
}
UndoDercorator.undoStack = [];
UndoDercorator.prototype.execute = function(){
UndoDercorator.undoStack.push(this.command);
this.command.execute();
}
UndoDercorator.prototype.undo = function(){
this.command.undo();
}
window.onload = function(){
var reciever = new Reciever();
var left = document.getElementById('left');
var right = document.getElementById('right');
var up = document.getElementById('up');
var down = document.getElementById('down');
var undo = document.getElementById('undo');
var moveLeft = new UndoDercorator(new MoveLeft(reciever));
var moveRight = new UndoDercorator(new MoveRight(reciever));
var moveUp = new UndoDercorator(new MoveUp(reciever));
var moveDown = new UndoDercorator(new MoveDown(reciever));
left.addEventListener('click',function(){
moveLeft.execute();
})
right.addEventListener('click',function(){
moveRight.execute();
})
up.addEventListener('click',function(){
moveUp.execute();
})
down.addEventListener('click',function(){
moveDown.execute();
})
undo.addEventListener('click',function(){
if(UndoDercorator.undoStack.length>0){
var cmd = UndoDercorator.undoStack.pop();
cmd.undo();
}else{
alert('不能再回退了');
}
})
}
</script>
</head>
<body>
<div id = "div1"></div>
<input type="button" value="left" id="left">
<input type="button" value="right" id="right">
<input type="button" value="up" id="up">
<input type="button" value="down" id="down">
<input type="button" value="down" id="undo">
</body>
</html>
</code></pre></div></div>
Javascript设计模式(观察者模式与发布订阅模式)
2017-07-23T05:45:37+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/23/Javascript设计模式(观察者模式与发布订阅模式)
<blockquote>
<p>观察者和发布订阅模式设计模式定义了对象间的一种一对多的依赖关系,以便一个对象的状态发生变化时,所有依赖于它的对象都得到通知并自动刷新。此种模式通常被用来实现事件处理系统。</p>
</blockquote>
<p>观察者模式实例:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//被观察者(主体对象)</span>
<span class="kd">function</span> <span class="nx">Observable</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">obs</span> <span class="o">=</span> <span class="p">[];</span><span class="c1">//存储观察者列表</span>
<span class="p">}</span>
<span class="nx">Observable</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">attach</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">ob</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">obs</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">ob</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Observable</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">notify</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">obs</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">ob</span><span class="p">){</span>
<span class="nx">ob</span><span class="p">.</span><span class="nx">update</span><span class="p">();</span>
<span class="p">})</span>
<span class="p">}</span>
<span class="c1">//观察者对象</span>
<span class="kd">function</span> <span class="nx">Watcher</span><span class="p">(</span><span class="nx">name</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span>
<span class="p">}</span>
<span class="nx">Watcher</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">update</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">subject</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Observable</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">ob1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Watcher</span><span class="p">(</span><span class="dl">'</span><span class="s1">1</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">ob2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Watcher</span><span class="p">(</span><span class="dl">'</span><span class="s1">2</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">subject</span><span class="p">.</span><span class="nx">attach</span><span class="p">(</span><span class="nx">ob1</span><span class="p">).</span><span class="nx">attach</span><span class="p">(</span><span class="nx">ob2</span><span class="p">);</span>
<span class="nx">subject</span><span class="p">.</span><span class="nx">notify</span><span class="p">();</span>
</code></pre></div></div>
<p>发布订阅模式实例:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">Event</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">subs</span> <span class="o">=</span> <span class="p">{};</span>
<span class="p">}</span>
<span class="nx">Event</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">on</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">cb</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">subs</span><span class="p">[</span><span class="nx">name</span><span class="p">]){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">subs</span><span class="p">[</span><span class="nx">name</span><span class="p">]</span><span class="o">=</span><span class="nx">cb</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">Event</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">trigger</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nx">name</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">subs</span><span class="p">[</span><span class="nx">name</span><span class="p">]()</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">key</span> <span class="k">in</span> <span class="k">this</span><span class="p">.</span><span class="nx">subs</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">subs</span><span class="p">[</span><span class="nx">key</span><span class="p">]()</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">e</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Event</span><span class="p">();</span>
<span class="nx">e</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">e1</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">e1</span><span class="dl">'</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">e</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">e2</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">e2</span><span class="dl">'</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">e</span><span class="p">.</span><span class="nx">trigger</span><span class="p">(</span><span class="dl">'</span><span class="s1">e1</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">e</span><span class="p">.</span><span class="nx">trigger</span><span class="p">();</span>
</code></pre></div></div>
<p>可以看到,观察者模式和发布订阅模式还是有一些区别的,在观察者模式中,至少需要两个对象(主体对象即被观察者和观察者),所有观察者都需要实现一个统一的接口(update)供被观察者调用,观察者和被观察者存在一定的联系;而发布订阅模式则没有此种限制。</p>
Javascript设计模式(代理模式)
2017-07-22T14:35:41+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/22/Javascript设计模式(代理模式)
<blockquote>
<p>代理模式的目的就是为了节制(控制)对本体对象的访问,代理对象和本体对象都实现了相同的接口。代理模式可以用来延迟对象的初始化,增强加载速度。</p>
</blockquote>
<p>实例:</p>
<p>假设有一个书店对象,其有很多业务,加载这个书店对象需要消耗大量内存,如果程序一开始就初始化这个对象,可能会耗费珍贵的加载时间,而且真正的购买动作往往是用户选购很长时间后才发生,这时我们就可以实现一个代理对象来完成业务逻辑,等到业务正真发生时再去初始化书店对象。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Book</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">,</span><span class="nx">num</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">year</span> <span class="o">=</span> <span class="nx">year</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="nx">type</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">num</span> <span class="o">=</span> <span class="nx">num</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Book</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span><span class="o">+</span><span class="dl">'</span><span class="s1">,</span><span class="dl">'</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">year</span><span class="o">+</span><span class="dl">'</span><span class="s1">,</span><span class="dl">'</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">type</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//假设BookStore是一个很大的对象</span>
<span class="kd">var</span> <span class="nx">BookStore</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">books</span> <span class="o">=</span> <span class="p">[];</span>
<span class="p">}</span>
<span class="nx">BookStore</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">constructor</span><span class="p">:</span> <span class="nx">BookStore</span><span class="p">,</span>
<span class="na">sellBook</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">book</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">findBook</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="nx">book</span> <span class="o">&&</span> <span class="nx">book</span><span class="p">.</span><span class="nx">num</span><span class="o">></span><span class="mi">1</span><span class="p">){</span>
<span class="nx">book</span><span class="p">.</span><span class="nx">num</span><span class="o">--</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">book</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="kc">null</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">addBook</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">books</span><span class="p">[</span><span class="nx">name</span><span class="o">+</span><span class="nx">year</span><span class="o">+</span><span class="nx">type</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Book</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">,</span><span class="mi">10000</span><span class="p">);</span>
<span class="p">},</span>
<span class="na">findBook</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">){</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">books</span><span class="p">[</span><span class="nx">name</span><span class="o">+</span><span class="nx">year</span><span class="o">+</span><span class="nx">type</span><span class="p">];</span>
<span class="p">}</span>
<span class="c1">//其他的业务</span>
<span class="p">}</span>
<span class="c1">//需要提供一个代理对象来延迟BookStore的初始化,真正用到的时候再加载,以提供程序的性能</span>
<span class="nx">BookStoreProxy</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){}</span>
<span class="nx">BookStoreProxy</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">constructor</span><span class="p">:</span> <span class="nx">BookStoreProxy</span><span class="p">,</span>
<span class="na">initialBookStore</span><span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">bookStore</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">bookStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">BookStore</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">sellBook</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">initialBookStore</span><span class="p">();</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">bookStore</span><span class="p">.</span><span class="nx">sellBook</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">);</span>
<span class="p">},</span>
<span class="na">addBook</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">initialBookStore</span><span class="p">();</span>
<span class="k">this</span><span class="p">.</span><span class="nx">bookStore</span><span class="p">.</span><span class="nx">addBook</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">);</span>
<span class="p">},</span>
<span class="na">findBook</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">initialBookStore</span><span class="p">();</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">bookStore</span><span class="p">.</span><span class="nx">findBook</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">//其他的业务</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">bookStoreProxy</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">BookStoreProxy</span><span class="p">();</span>
<span class="nx">bookStoreProxy</span><span class="p">.</span><span class="nx">addBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">JavaScript</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">软件</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">bookStoreProxy</span><span class="p">.</span><span class="nx">addBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">唐诗</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">文学</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">bookStoreProxy</span><span class="p">.</span><span class="nx">addBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">高数</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">数理化</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">bookStoreProxy</span><span class="p">.</span><span class="nx">sellBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">JavaScript</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">软件</span><span class="dl">'</span><span class="p">).</span><span class="nx">toString</span><span class="p">());</span>
</code></pre></div></div>
Javascript设计模式(享元模式)
2017-07-22T12:57:08+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/22/Javascript设计模式(享元模式)
<blockquote>
<p>享元模式使用共享物件,用来尽可能减少内存使用量以及分享资讯给尽可能多的相似物件;它适合用于只是因重复而导致使用无法令人接受的大量内存的大量物件。通常物件中的部分状态是可以分享。常见做法是把它们放在外部数据结构,当需要使用时再将它们传递给享元。</p>
</blockquote>
<p>实例:</p>
<p>假设有一个书店,其有一个固定的印刷厂,书店卖的书有书名,年份,类别,购买者4个属性,其中卖的大多数书会有相同的书名、年份和类别属性,只有购买者属性不一样,这时就可以将书名、年份和类别属性放在外部的数据结构。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Book</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">year</span> <span class="o">=</span> <span class="nx">year</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">type</span> <span class="o">=</span> <span class="nx">type</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">BookSelled</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">book</span><span class="p">,</span><span class="nx">owner</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">book</span> <span class="o">=</span> <span class="nx">book</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">owner</span> <span class="o">=</span> <span class="nx">owner</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">BookSelled</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">book</span><span class="p">.</span><span class="nx">name</span><span class="o">+</span><span class="dl">'</span><span class="s1">,</span><span class="dl">'</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">book</span><span class="p">.</span><span class="nx">year</span><span class="o">+</span><span class="dl">'</span><span class="s1">,</span><span class="dl">'</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">book</span><span class="p">.</span><span class="nx">type</span><span class="o">+</span><span class="dl">'</span><span class="s1">,</span><span class="dl">'</span><span class="o">+</span><span class="k">this</span><span class="p">.</span><span class="nx">owner</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">BookFactory</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">books</span> <span class="o">=</span> <span class="p">[];</span>
<span class="p">}</span>
<span class="nx">BookFactory</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">constructor</span><span class="p">:</span> <span class="nx">BookFactory</span><span class="p">,</span>
<span class="na">creatBook</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="k">this</span><span class="p">.</span><span class="nx">books</span><span class="p">[</span><span class="nx">name</span><span class="o">+</span><span class="nx">year</span><span class="o">+</span><span class="nx">type</span><span class="p">]){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">books</span><span class="p">[</span><span class="nx">name</span><span class="o">+</span><span class="nx">year</span><span class="o">+</span><span class="nx">type</span><span class="p">]</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Book</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">books</span><span class="p">[</span><span class="nx">name</span><span class="o">+</span><span class="nx">year</span><span class="o">+</span><span class="nx">type</span><span class="p">];</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nx">BookStore</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">bookFactory</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">bookFactory</span><span class="o">=</span><span class="nx">bookFactory</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">BookStore</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">constructor</span><span class="p">:</span> <span class="nx">BookStore</span><span class="p">,</span>
<span class="na">sellBook</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">,</span><span class="nx">owner</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">book</span> <span class="o">=</span> <span class="k">this</span><span class="p">.</span><span class="nx">bookFactory</span><span class="p">.</span><span class="nx">creatBook</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">year</span><span class="p">,</span><span class="nx">type</span><span class="p">);</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">BookSelled</span><span class="p">(</span><span class="nx">book</span><span class="p">,</span><span class="nx">owner</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">bookStore</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">BookStore</span><span class="p">(</span><span class="k">new</span> <span class="nx">BookFactory</span><span class="p">());</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">bookStore</span><span class="p">.</span><span class="nx">sellBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">JavaScript</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">软件</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">lisong</span><span class="dl">'</span><span class="p">).</span><span class="nx">toString</span><span class="p">());</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">bookStore</span><span class="p">.</span><span class="nx">sellBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">唐诗</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">文学</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">).</span><span class="nx">toString</span><span class="p">());</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">bookStore</span><span class="p">.</span><span class="nx">sellBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">JavaScript</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">软件</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">用户1</span><span class="dl">'</span><span class="p">).</span><span class="nx">toString</span><span class="p">());</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">bookStore</span><span class="p">.</span><span class="nx">sellBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">JavaScript</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">软件</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">用户2</span><span class="dl">'</span><span class="p">).</span><span class="nx">toString</span><span class="p">());</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">bookStore</span><span class="p">.</span><span class="nx">sellBook</span><span class="p">(</span><span class="dl">'</span><span class="s1">唐诗</span><span class="dl">'</span><span class="p">,</span><span class="mi">2017</span><span class="p">,</span><span class="dl">'</span><span class="s1">文学</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">用户3</span><span class="dl">'</span><span class="p">).</span><span class="nx">toString</span><span class="p">());</span>
</code></pre></div></div>
<p>享元模式可以减少程序运行所需要的空间,但是相应的会增加运行的时间,需要平衡两者的关系,过分使用也不好</p>
git常用命令
2017-07-22T07:27:47+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/07/22/git常用命令
<blockquote>
<p>git是一个分布式的版本管理系统,没有服务端和客户端的概率,不过在团队协作中,通常会选一台客户端作为服务器,方便成员之间的push与pull</p>
</blockquote>
<h2 id="git-的结构">git 的结构</h2>
<p>git分为工作区,暂存区,版本库:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-07-22-git常用命令-1.jpg" alt="" /></p>
<p>工作区有一个隐藏目录.Git,这个不算工作区,而是 git 的版本库。其中有一个<code class="language-plaintext highlighter-rouge">index</code>的文件,其记录了暂存区的索引。</p>
<p>注意:所有被跟踪的文件在暂存区都有相应的索引,当<code class="language-plaintext highlighter-rouge">index</code>中没有要提交的索引时,其和当前分支的历史记录所有得索引是一致的。分支只能操作被暂存区跟踪(track)了的文件。</p>
<h2 id="撤销操作">撤销操作</h2>
<h3 id="git-checkout----dirfile"><code class="language-plaintext highlighter-rouge">git checkout -- [dir|file]</code></h3>
<p>git checkout 后面跟– 可以将暂存区内的内容恢复到工作区,从而撤销工作区的修改</p>
<h3 id="git-chekout-commitid----dirfile"><code class="language-plaintext highlighter-rouge">git chekout commitid -- [dir|file]</code></h3>
<p>也可以将某个提交恢复到工作区和暂存区,从而撤销工作区的修改,并且add到暂存区</p>
<h3 id="git-reset-commitid----dirfile"><code class="language-plaintext highlighter-rouge">git reset commitid -- [dir|file]</code></h3>
<p>将某个提交恢复到暂存区,工作区不变:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-07-22-git常用命令-2.png" alt="" /></p>
<h3 id="git-revert-commitid"><code class="language-plaintext highlighter-rouge">git revert commitid</code></h3>
<p><code class="language-plaintext highlighter-rouge">git revert</code> 可以撤销某个提交的操作,并且生成一个新的<code class="language-plaintext highlighter-rouge">commit</code>:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-07-22-git常用命令-3.png" alt="" /></p>
<p>红色部分为当前分支最新的内容,蓝色部分为需要撤销的那个commit之前的内容</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-07-22-git常用命令-4.png" alt="" /></p>
<p>注意:需要<code class="language-plaintext highlighter-rouge">revert</code>的那个<code class="language-plaintext highlighter-rouge">commitid</code>之后如果对同一个文件有过修改才会产生冲突</p>
<h2 id="回退操作">回退操作</h2>
<p><a href="https://wanls4583.github.io/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/03/27/git%E5%9B%9E%E9%80%80/">回退操作</a></p>
<h2 id="回滚远程仓库">回滚远程仓库</h2>
<h3 id="git-push---force-origin-master"><code class="language-plaintext highlighter-rouge">git push --force origin master</code></h3>
<p>reset 到某个版本后,可以使用该命令强制推送到远程仓库,回滚远程仓库代码</p>
<h3 id="git-reset---hard-originmaster"><code class="language-plaintext highlighter-rouge">git reset --hard origin/master</code></h3>
<p>同步远程代码到本地仓库</p>
<h2 id="分支切换操作">分支切换操作</h2>
<h3 id="git-branch-branchname-"><code class="language-plaintext highlighter-rouge">git branch branchname </code></h3>
<p>在当前最新提交下新建分支,不会切换到新分支</p>
<h3 id="git-branch--d-d-branchname-"><code class="language-plaintext highlighter-rouge">git branch -d|-D branchname </code></h3>
<p>-d删除已经merge过的分支,-D强制可以删除未merge的分支</p>
<h3 id="git-checkout-commitid"><code class="language-plaintext highlighter-rouge">git checkout commitid</code></h3>
<p><code class="language-plaintext highlighter-rouge">commitid</code>指向的是一个提交,该命令可以将工作区和暂存区切换到某一个具体提交或者某一个分支,当切换到某一个具体提交时,将进入<code class="language-plaintext highlighter-rouge">datached HEAD</code>状态,此时可以在该提交下新建新的分支:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-07-22-git常用命令-5.png" alt="" /></p>
<h3 id="git-checkout--b-branchname"><code class="language-plaintext highlighter-rouge">git checkout -b branchname</code></h3>
<p>在当前最新提交下新建分支,并切换到新分支</p>
<h3 id="git-checkout--b-branchname-commitid"><code class="language-plaintext highlighter-rouge">git checkout -b branchname commitid</code></h3>
<p>该命令相当于<code class="language-plaintext highlighter-rouge">git checkout commitid</code>和<code class="language-plaintext highlighter-rouge">git checkout -b branchname</code>的组合</p>
<h2 id="修改commit注释">修改commit注释</h2>
<h3 id="git-commit---amend"><code class="language-plaintext highlighter-rouge">git commit --amend</code></h3>
<p>该命令可以生成一个新的提交,覆盖掉当前分支最新的一次提交,利用这个特性,可以在不提交新内容的情况下修改最后一次提交的注释(commitid 将改变),也可以提交新内容后覆盖最后一次提交。</p>
<h2 id="其他">其他</h2>
<h3 id="git-diff---name-only-commit-1-commit-2-"><code class="language-plaintext highlighter-rouge">git diff --name-only <commit-1> <commit-2> </code></h3>
<p>获取两次提交之间修改的文件</p>
<h3 id="git-diff---name-only-head-head"><code class="language-plaintext highlighter-rouge">git diff --name-only HEAD~ HEAD</code></h3>
<p>获取最近依次提交修改的文件</p>
Javascript设计模式(装饰者模式)
2017-07-17T13:13:15+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/17/Javascript设计模式(装饰者模式)
<blockquote>
<p>装饰者模式可以在保证不改变原有对象的基础上,去扩展一些原有的方法</p>
</blockquote>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">BH</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">extend</span><span class="p">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">me</span><span class="p">,</span><span class="nx">superConstructor</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">F</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="nx">F</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nx">superConstructor</span><span class="p">.</span><span class="nx">prototype</span><span class="p">;</span>
<span class="nx">me</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">F</span><span class="p">();</span>
<span class="nx">me</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="kd">constructor</span> <span class="o">=</span> <span class="nx">me</span><span class="p">;</span>
<span class="nx">me</span><span class="p">.</span><span class="nx">superClass</span> <span class="o">=</span> <span class="nx">superConstructor</span><span class="p">.</span><span class="nx">prototype</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">Programmer</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">programmer</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">programmer</span> <span class="o">=</span><span class="nx">programmer</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Programmer</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">constructor</span> <span class="p">:</span> <span class="nx">Programmer</span><span class="p">,</span>
<span class="na">skill</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">会用电脑 </span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">JsProgrammer</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">programmer</span><span class="p">){</span>
<span class="nx">JsProgrammer</span><span class="p">.</span><span class="nx">superClass</span><span class="p">.</span><span class="kd">constructor</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="nx">programmer</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">BH</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">JsProgrammer</span><span class="p">,</span><span class="nx">Programmer</span><span class="p">);</span>
<span class="nx">JsProgrammer</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">constructor</span><span class="p">:</span> <span class="nx">JsProgrammer</span><span class="p">,</span>
<span class="na">skill</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">programmer</span><span class="p">.</span><span class="nx">skill</span><span class="p">()</span><span class="o">+</span><span class="dl">'</span><span class="s1">,会javascript </span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">JavaProgrammer</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">programmer</span><span class="p">){</span>
<span class="nx">JsProgrammer</span><span class="p">.</span><span class="nx">superClass</span><span class="p">.</span><span class="kd">constructor</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span><span class="nx">programmer</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">BH</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">JavaProgrammer</span><span class="p">,</span><span class="nx">Programmer</span><span class="p">);</span>
<span class="nx">JavaProgrammer</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">constructor</span><span class="p">:</span> <span class="nx">JavaProgrammer</span><span class="p">,</span>
<span class="na">skill</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">programmer</span><span class="p">.</span><span class="nx">skill</span><span class="p">()</span><span class="o">+</span><span class="dl">'</span><span class="s1">,会java </span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">programmer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Programmer</span><span class="p">();</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">programmer</span><span class="p">.</span><span class="nx">skill</span><span class="p">());</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="dl">'</span><span class="s1">
--------------------------------
</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">programmer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JsProgrammer</span><span class="p">(</span><span class="nx">programmer</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">programmer</span><span class="p">.</span><span class="nx">skill</span><span class="p">());</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="dl">'</span><span class="s1">
--------------------------------
</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">programmer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">JavaProgrammer</span><span class="p">(</span><span class="nx">programmer</span><span class="p">);</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="nx">programmer</span><span class="p">.</span><span class="nx">skill</span><span class="p">());</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="dl">'</span><span class="s1">
--------------------------------
</span><span class="dl">'</span><span class="p">);</span>
</code></pre></div></div>
Javascript设计模式(适配器模式)
2017-07-16T07:25:48+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/16/Javascript设计模式(适配器模式)
<blockquote>
<p>在计算机编程中,适配器模式(有时候也称包装样式或者包装)将一个类(对象)的接口适配成用户所期待的。一个适配允许通常因为接口(对象)不兼容而不能在一起工作的类(对象)工作在一起,做法是将类(对象)自己的接口包裹在一个已存在的类(对象)中。</p>
</blockquote>
<p>从表面看,适配器模式很像门面模式。她们都要对别的对象进行包装并改变其呈现的接口。二者的区别在于她们如何改变接口:</p>
<ul>
<li>门面元素展现的是一个简化的接口,她并不提供额外的选择</li>
<li>适配器则要把一个接口转换为另一个接口,她并不滤除某些能力,也不会简化接口</li>
</ul>
<p>示例:</p>
<p>假设有个库的一个方法是用来打印元素内容的</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">alertCont</span><span class="p">(</span><span class="nx">el</span><span class="p">){</span>
<span class="nx">alert</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">el</span><span class="p">.</span><span class="nx">innerHTML</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>现在的需求是不改变原有库的基础上把参数换成元素id,此时就可以用到适配器了</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">alertContAdapter</span><span class="p">(</span><span class="nx">id</span><span class="p">){</span>
<span class="nx">alertCont</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="nx">id</span><span class="p">))</span>
<span class="p">}</span>
</code></pre></div></div>
<p><em>使用场景</em>:适配器适用于客户系统期待的接口与现有API提供的接口不兼容这种场合。她只能用来协调语法上的差异问题。</p>
Javascript设计模式(门面模式)
2017-07-16T06:36:32+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/16/Javascript设计模式(门面模式)
<blockquote>
<p>门面模式,是指提供一个统一的接口去访问多个子系统的多个不同的接口,它为子系统中的一组接口提供一个统一的高层接口。使得子系统更容易使用。在JavaScript中,这些子系统可以是一段复杂的代码或者是一个复杂的函数。</p>
</blockquote>
<p><em>一个简单的门面模式</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">addEvent</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">el</span><span class="p">,</span> <span class="nx">ty</span><span class="p">,</span> <span class="nx">fn</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">cases</span> <span class="o">=</span> <span class="p">[</span>
<span class="kd">function</span><span class="p">(</span><span class="nx">el</span><span class="p">,</span> <span class="nx">ty</span><span class="p">,</span> <span class="nx">fn</span><span class="p">)</span> <span class="p">{</span> <span class="nx">el</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="nx">ty</span><span class="p">,</span> <span class="nx">fn</span><span class="p">,</span> <span class="kc">false</span><span class="p">);</span> <span class="p">},</span>
<span class="kd">function</span><span class="p">(</span><span class="nx">el</span><span class="p">,</span> <span class="nx">ty</span><span class="p">,</span> <span class="nx">fn</span><span class="p">)</span> <span class="p">{</span> <span class="nx">el</span><span class="p">.</span><span class="nx">attachEvent</span><span class="p">(</span><span class="dl">'</span><span class="s1">on</span><span class="dl">'</span><span class="o">+</span><span class="nx">ty</span><span class="p">,</span> <span class="nx">fn</span><span class="p">);</span> <span class="p">},</span>
<span class="kd">function</span><span class="p">(</span><span class="nx">el</span><span class="p">,</span> <span class="nx">ty</span><span class="p">,</span> <span class="nx">fn</span><span class="p">)</span> <span class="p">{</span> <span class="nx">el</span><span class="p">[</span><span class="dl">'</span><span class="s1">on</span><span class="dl">'</span><span class="o">+</span><span class="nx">ty</span><span class="p">]</span> <span class="o">=</span> <span class="nx">fn</span><span class="p">;</span> <span class="p">}</span>
<span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="nx">el</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">){</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">addEvent</span> <span class="o">=</span> <span class="nx">cases</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="p">}</span><span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nx">el</span><span class="p">.</span><span class="nx">attachEvent</span><span class="p">){</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">addEvent</span> <span class="o">=</span> <span class="nx">cases</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">addEvent</span> <span class="o">=</span> <span class="nx">cases</span><span class="p">[</span><span class="mi">2</span><span class="p">];</span>
<span class="p">}</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">addEvent</span><span class="p">(</span><span class="nx">el</span><span class="p">,</span> <span class="nx">ty</span><span class="p">,</span> <span class="nx">fn</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>addEvent函数就是一个基本的门面,把检查代码封装在一个地方,这可以让代码变得更简洁,便于之后的重复使用。</p>
<p><em>便利门面函数</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">a</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">x</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">b</span><span class="p">(</span><span class="nx">x</span><span class="p">){</span>
<span class="k">return</span> <span class="nx">y</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">ab</span><span class="p">(</span><span class="nx">x</span><span class="p">,</span> <span class="nx">y</span><span class="p">){</span>
<span class="nx">a</span><span class="p">(</span><span class="nx">x</span><span class="p">);</span>
<span class="nx">b</span><span class="p">(</span><span class="nx">y</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>将多个函数组合起来,而不是将多个函数里的代码直接放在门面函数里可以使得之后的维护更加灵活。</p>
<p><em>门面模式的使用场合</em>:需要重复使用一组函数或者代码</p>
Javascript设计模式(组合模式)
2017-07-15T19:28:53+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/15/Javascript设计模式(组合模式)
<blockquote>
<p>组合模式,将对象组合成树形结构以表示“部分-整体”的层次结构,组合模式使得用户对单个对象和组合对象的使用具有一致性。</p>
</blockquote>
<p>实例:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Util</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">forEach</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">items</span><span class="p">,</span><span class="nx">fn</span><span class="p">,</span><span class="nx">args</span><span class="p">){</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">items</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">fn</span><span class="p">.</span><span class="nx">apply</span><span class="p">(</span><span class="nx">items</span><span class="p">[</span><span class="nx">i</span><span class="p">],</span><span class="nx">args</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">wirteLine</span><span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="dl">'</span><span class="s1">
--------------------------------
</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">Compsite</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">childs</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Compsite</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">addChild</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">child</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">childs</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">child</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">Compsite</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">doWorking</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">===</span> <span class="nx">name</span> <span class="o">||</span> <span class="o">!</span><span class="nx">name</span><span class="p">){</span>
<span class="c1">//如果是叶子节点</span>
<span class="k">if</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">childs</span><span class="p">.</span><span class="nx">length</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span>
<span class="nb">document</span><span class="p">.</span><span class="nx">write</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">name</span><span class="o">+</span><span class="dl">'</span><span class="s1">在工作 </span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nx">Util</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">childs</span><span class="p">,</span><span class="k">this</span><span class="p">.</span><span class="nx">doWorking</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="nx">Util</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">childs</span><span class="p">,</span><span class="k">this</span><span class="p">.</span><span class="nx">doWorking</span><span class="p">,[</span><span class="nx">name</span><span class="p">]);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">company</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">公司</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">dept1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">部门1</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">dept2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">部门2</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">dept3</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">部门3</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">ol1_1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工1_1</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">ol1_2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工1_2</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">ol2_1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工2_1</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">ol2_2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工2_2</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">ol3_1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工3_1</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">ol3_2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Compsite</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工3_2</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">company</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">dept1</span><span class="p">);</span>
<span class="nx">company</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">dept2</span><span class="p">);</span>
<span class="nx">company</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">dept3</span><span class="p">);</span>
<span class="nx">dept1</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">ol1_1</span><span class="p">);</span>
<span class="nx">dept1</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">ol1_2</span><span class="p">);</span>
<span class="nx">dept2</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">ol2_1</span><span class="p">);</span>
<span class="nx">dept2</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">ol2_2</span><span class="p">);</span>
<span class="nx">dept3</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">ol3_1</span><span class="p">);</span>
<span class="nx">dept3</span><span class="p">.</span><span class="nx">addChild</span><span class="p">(</span><span class="nx">ol3_2</span><span class="p">);</span>
<span class="nx">company</span><span class="p">.</span><span class="nx">doWorking</span><span class="p">();</span>
<span class="nx">Util</span><span class="p">.</span><span class="nx">wirteLine</span><span class="p">();</span>
<span class="nx">company</span><span class="p">.</span><span class="nx">doWorking</span><span class="p">(</span><span class="dl">'</span><span class="s1">部门1</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">Util</span><span class="p">.</span><span class="nx">wirteLine</span><span class="p">();</span>
<span class="nx">company</span><span class="p">.</span><span class="nx">doWorking</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工1_1</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">Util</span><span class="p">.</span><span class="nx">wirteLine</span><span class="p">();</span>
<span class="nx">dept1</span><span class="p">.</span><span class="nx">doWorking</span><span class="p">(</span><span class="dl">'</span><span class="s1">员工1_2</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">Util</span><span class="p">.</span><span class="nx">wirteLine</span><span class="p">();</span>
<span class="nx">ol3_2</span><span class="p">.</span><span class="nx">doWorking</span><span class="p">();</span>
</code></pre></div></div>
<p>在上面的实例中,公司、部门、员工都具有相同的行为,其中,公司和部门是组合对象,员工是单个对象,可以像操作单个对象一样操作组合对象。组合对象、单个对象可以继续组合成组合对象。</p>
<p>组合模式使用场景:</p>
<ul>
<li>你想表示对象的部分-整体层次结构</li>
<li>你希望用户忽略组合对象与单个对象的不同,用户将统一地使用组合结构中的所有对象</li>
</ul>
Javascript设计模式(工厂模式)
2017-07-09T05:54:21+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/09/Javascript设计模式(工厂模式)
<blockquote>
<p>工厂设计模式分为简单工厂和抽象工厂,简单工厂即将生产实例的方法分离出来,抽象工厂会抽象出一个方法来生产实例,而真正的实现则交给子类去实现。</p>
</blockquote>
<h3 id="未使用工厂模式">未使用工厂模式:</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Dell</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">戴尔电脑</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">Lenovo</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">联想电脑</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">ComputerShop</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="nx">ComputerShop</span><span class="p">.</span><span class="nx">prototype</span><span class="o">=</span><span class="p">{</span>
<span class="na">Constructor</span> <span class="p">:</span> <span class="nx">ComputerShop</span><span class="p">,</span>
<span class="c1">//卖电脑</span>
<span class="na">sellComputer</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">type</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">computer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">type</span><span class="o">==</span><span class="dl">'</span><span class="s1">Dell</span><span class="dl">'</span><span class="p">){</span>
<span class="nx">computer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Dell</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nx">type</span><span class="o">==</span><span class="dl">'</span><span class="s1">Lenovo</span><span class="dl">'</span><span class="p">){</span>
<span class="nx">computer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Lenovo</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">computer</span><span class="p">;</span>
<span class="p">},</span>
<span class="c1">//维修电脑</span>
<span class="na">service</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">维修电脑</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="c1">//其他服务....</span>
<span class="p">}</span>
<span class="k">new</span> <span class="nx">ComputerShop</span><span class="p">().</span><span class="nx">sellComputer</span><span class="p">(</span><span class="dl">'</span><span class="s1">Dell</span><span class="dl">'</span><span class="p">);</span>
</code></pre></div></div>
<h3 id="简单工厂模式">简单工厂模式</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Dell</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">戴尔电脑</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">Lenovo</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">联想电脑</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">ComputerFactory</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">createComputer</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">type</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">computer</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="nx">type</span><span class="o">==</span><span class="dl">'</span><span class="s1">Dell</span><span class="dl">'</span><span class="p">){</span>
<span class="nx">computer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Dell</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="nx">type</span><span class="o">==</span><span class="dl">'</span><span class="s1">Lenovo</span><span class="dl">'</span><span class="p">){</span>
<span class="nx">computer</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Lenovo</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">computer</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">ComputerShop</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="nx">ComputerShop</span><span class="p">.</span><span class="nx">prototype</span><span class="o">=</span><span class="p">{</span>
<span class="na">Constructor</span> <span class="p">:</span> <span class="nx">ComputerShop</span><span class="p">,</span>
<span class="c1">//卖电脑</span>
<span class="na">sellComputer</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">type</span><span class="p">){</span>
<span class="c1">//交给工厂去生产实例</span>
<span class="k">return</span> <span class="nx">ComputerFactory</span><span class="p">.</span><span class="nx">createComputer</span><span class="p">(</span><span class="nx">type</span><span class="p">);</span>
<span class="p">},</span>
<span class="c1">//维修电脑</span>
<span class="na">service</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">维修电脑</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="c1">//其他服务....</span>
<span class="p">}</span>
<span class="k">new</span> <span class="nx">ComputerShop</span><span class="p">().</span><span class="nx">sellComputer</span><span class="p">(</span><span class="dl">'</span><span class="s1">Dell</span><span class="dl">'</span><span class="p">);</span>
</code></pre></div></div>
<p>简单工厂可以由动态工厂来实现</p>
<h3 id="抽象工厂模式">抽象工厂模式</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">BH</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">extend</span><span class="p">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">me</span><span class="p">,</span><span class="nx">superConstructor</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">F</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="nx">F</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nx">superConstructor</span><span class="p">.</span><span class="nx">prototype</span><span class="p">;</span>
<span class="nx">me</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">F</span><span class="p">();</span>
<span class="nx">me</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">Constructor</span> <span class="o">=</span> <span class="nx">me</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">Dell</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">戴尔电脑</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">Lenovo</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">联想电脑</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">ComputerShop</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="nx">ComputerShop</span><span class="p">.</span><span class="nx">prototype</span><span class="o">=</span><span class="p">{</span>
<span class="na">Constructor</span> <span class="p">:</span> <span class="nx">ComputerShop</span><span class="p">,</span>
<span class="c1">//卖电脑</span>
<span class="na">sellComputer</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">type</span><span class="p">){</span>
<span class="k">throw</span> <span class="nb">Error</span><span class="p">(</span><span class="dl">'</span><span class="s1">抽象工厂不能实例化类</span><span class="dl">'</span><span class="p">);</span>
<span class="p">},</span>
<span class="c1">//维修电脑</span>
<span class="na">service</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">维修电脑</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="c1">//其他服务....</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">DellComputerShop</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){}</span>
<span class="nx">BH</span><span class="p">.</span><span class="nx">extend</span><span class="p">(</span><span class="nx">DellComputerShop</span><span class="p">,</span><span class="nx">ComputerShop</span><span class="p">);</span>
<span class="nx">DellComputerShop</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">sellComputer</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Dell</span><span class="p">();</span>
<span class="p">}</span>
<span class="k">new</span> <span class="nx">DellComputerShop</span><span class="p">().</span><span class="nx">sellComputer</span><span class="p">();</span>
</code></pre></div></div>
Javascript设计模式(桥模式)
2017-07-09T05:42:36+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/07/09/Javascript设计模式(桥模式)
<blockquote>
<p>桥接模式(Bridge)将抽象部分与它的实现部分分离,使它们都可以独立地变化。这里的抽象部分与实现部分不一定是抽象类与实现类的关系,不必拘泥其实现形式。利用桥接模式可以分离业务逻辑单元。</p>
</blockquote>
<h2 id="桥接实例">桥接实例</h2>
<h3 id="事件监听回调机制">事件监听回调机制</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<title>工厂模式</title>
</head>
<body>
<input type="button" name="" id="input1" value="123">
</body>
<script type="text/javascript">
var inp = document.getElementById('input1');
inp.addEventListener('click',function(){
alert(this.value);
/*$.ajax('GET','url?value='+this.value,function(){
console.log('Requested Beer: ' + resp.responseText);}
)*/
//其他的业务
})
</script>
</html>
</code></pre></div></div>
<p>可以看到,这里的前台事件绑定和后台请求业务逻辑是紧密结合的,我们如果想单独测试请求业务逻辑则必须点击按钮才能测试,又或者加入之后需要更改后台请求业务逻辑,则必须在回调函数里更改。这种前后台业务逻辑绑定在一起业务划分不够清晰,是不利于后期维护的。</p>
<p><em>使用桥接模式</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//1.前台业务逻辑</span>
<span class="kd">var</span> <span class="nx">inp</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">'</span><span class="s1">input1</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">inp</span><span class="p">.</span><span class="nx">addEventListener</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span><span class="nx">brige</span><span class="p">)</span>
<span class="c1">//使用桥模式桥接前后台业务逻辑</span>
<span class="kd">function</span> <span class="nx">brige</span><span class="p">(){</span>
<span class="nx">alert</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="p">);</span>
<span class="nx">getInfoByValue</span><span class="p">(</span><span class="k">this</span><span class="p">.</span><span class="nx">value</span><span class="p">)</span>
<span class="p">}</span>
<span class="c1">//后台业务逻辑</span>
<span class="kd">function</span> <span class="nx">getInfoByValue</span><span class="p">(</span><span class="nx">value</span><span class="p">){</span>
<span class="cm">/*$.ajax('GET','url?value='+value,function(){
console.log('Requested Info: ' + resp.responseText);}
)*/</span>
<span class="p">}</span>
</code></pre></div></div>
<p>利用桥模式很好的将事件回调函数(属于前台业务逻辑)抽象出来,具体的后台业务交给另一个单元去实现,抽象部分代码和实现部分代码可以独立的更改其内部逻辑,又结合在一起。</p>
<h3 id="特权函数">特权函数</h3>
<p>特权函数是桥模式的一种实现,它将对外接口抽象出来,使其和内部具体实现分离。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">PublicClass</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">privateMethod</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">alert</span><span class="p">(</span><span class="dl">'</span><span class="s1">这里处理了很复杂的业务逻辑</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="nx">brigeMethod</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">alert</span><span class="p">(</span><span class="dl">'</span><span class="s1">调用了内部函数</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="nx">privateMethod</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">new</span> <span class="nx">PublicClass</span><span class="p">().</span><span class="nx">brigeMethod</span><span class="p">();</span>
</code></pre></div></div>
<h3 id="用桥把多个单体组织在一起">用桥把多个单体组织在一起</h3>
<p>假如有两个处理单元,它们之间是没有业务联系的,现在有个新业务需要同时用到这两个处理单元,这是可以使用桥模式将它们组合起来。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Class1</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">a</span> <span class="o">=</span> <span class="nx">a</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">b</span> <span class="o">=</span> <span class="nx">b</span><span class="p">;</span>
<span class="c1">//处理加法运算业务</span>
<span class="k">this</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">(</span><span class="nx">a</span><span class="o">+</span><span class="nx">b</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">Class2</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">c</span><span class="p">,</span><span class="nx">d</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">c</span> <span class="o">=</span> <span class="nx">c</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">d</span> <span class="o">=</span> <span class="nx">d</span><span class="p">;</span>
<span class="c1">//处理乘法运算业务</span>
<span class="k">this</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">(</span><span class="nx">c</span><span class="o">*</span><span class="nx">d</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">brigeMethod</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">c</span><span class="p">,</span><span class="nx">d</span><span class="p">){</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">Class1</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">).</span><span class="nx">run</span><span class="p">()</span><span class="o">+</span><span class="k">new</span> <span class="nx">Class2</span><span class="p">(</span><span class="nx">c</span><span class="p">,</span><span class="nx">d</span><span class="p">).</span><span class="nx">run</span><span class="p">();</span>
<span class="p">}</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">brigeMethod</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">));</span>
</code></pre></div></div>
html-Emmet语法
2017-07-04T03:19:06+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/07/04/html-Emmet语法
<h2 id="后代">后代:></h2>
<p>缩写:nav>ul>li</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><nav>
<ul>
<li></li>
</ul>
</nav>
</code></pre></div></div>
<h2 id="兄弟">兄弟:+</h2>
<p>缩写:div+p+bq</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div></div>
<p></p>
<blockquote></blockquote>
</code></pre></div></div>
<h2 id="上级">上级:^</h2>
<p>缩写:div+div>p>span+em^bq</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div></div>
<div>
<p><span></span><em></em></p>
<blockquote></blockquote>
</div>
</code></pre></div></div>
<p>缩写:div+div>p>span+em^^bq</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div></div>
<div>
<p><span></span><em></em></p>
</div>
<blockquote></blockquote>
</code></pre></div></div>
<h2 id="分组">分组:()</h2>
<p>缩写:div>(header>ul>li*2>a)+footer>p</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div>
<header>
<ul>
<li><a href=""></a></li>
<li><a href=""></a></li>
</ul>
</header>
<footer>
<p></p>
</footer>
</div>
</code></pre></div></div>
<p>缩写:(div>dl>(dt+dd)*3)+footer>p</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div>
<dl>
<dt></dt>
<dd></dd>
<dt></dt>
<dd></dd>
<dt></dt>
<dd></dd>
</dl>
</div>
<footer>
<p></p>
</footer>
</code></pre></div></div>
<h2 id="乘法">乘法:*</h2>
<p>缩写:ul>li*5</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ul>
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
</code></pre></div></div>
<h2 id="自增符号">自增符号:$</h2>
<p>缩写:ul>li.item$*5</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ul>
<li class="item1"></li>
<li class="item2"></li>
<li class="item3"></li>
<li class="item4"></li>
<li class="item5"></li>
</ul>
</code></pre></div></div>
<p>缩写:h$[title=item$]{Header $}*3</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><h1 title="item1">Header 1</h1>
<h2 title="item2">Header 2</h2>
<h3 title="item3">Header 3</h3>
</code></pre></div></div>
<p>缩写:ul>li.item$$$*5</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ul>
<li class="item001"></li>
<li class="item002"></li>
<li class="item003"></li>
<li class="item004"></li>
<li class="item005"></li>
</ul>
</code></pre></div></div>
<p>缩写:ul>li.item$@-*5</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ul>
<li class="item5"></li>
<li class="item4"></li>
<li class="item3"></li>
<li class="item2"></li>
<li class="item1"></li>
</ul>
</code></pre></div></div>
<p>缩写:ul>li.item$@3*5</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ul>
<li class="item3"></li>
<li class="item4"></li>
<li class="item5"></li>
<li class="item6"></li>
<li class="item7"></li>
</ul>
</code></pre></div></div>
<h2 id="id和类属性">ID和类属性</h2>
<p>缩写:#header</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div id="header"></div>
</code></pre></div></div>
<p>缩写:.title</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div class="title"></div>
</code></pre></div></div>
<p>缩写:form#search.wide</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><form id="search" class="wide"></form>
</code></pre></div></div>
<p>缩写:p.class1.class2.class3</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><p class="class1 class2 class3"></p>
</code></pre></div></div>
<h2 id="自定义属性">自定义属性</h2>
<p>缩写:p[title=”Hello world”]</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><p title="Hello world"></p>
</code></pre></div></div>
<p>缩写:td[rowspan=2 colspan=3 title]</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><td rowspan="2" colspan="3" title=""></td>
</code></pre></div></div>
<p>缩写:[a=’value1’ b=”value2”]</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div a="value1" b="value2"></div>
</code></pre></div></div>
<h2 id="文本">文本:{}</h2>
<p>缩写:a{Click me}</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><a href="">Click me</a>
</code></pre></div></div>
<p>缩写:p>{Click }+a{here}+{ to continue}</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><p>Click <a href="">here</a> to continue</p>
</code></pre></div></div>
<h2 id="隐式标签">隐式标签</h2>
<p>缩写:.class</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div class="class"></div>
</code></pre></div></div>
<p>缩写:em>.class</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><em><span class="class"></span></em>
</code></pre></div></div>
<p>缩写:ul>.class</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><ul>
<li class="class"></li>
</ul>
</code></pre></div></div>
<p>缩写:table>.row>.col</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><table>
<tr class="row">
<td class="col"></td>
</tr>
</table>
</code></pre></div></div>
<p>原文: <a href="http://www.w3cplus.com/tools/emmet-cheat-sheet.html © w3cplus.com">http://www.w3cplus.com/tools/emmet-cheat-sheet.html © w3cplus.com</a></p>
Angularjs学习笔记
2017-07-03T11:43:50+00:00
https://blog.lisong.hn.cn/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/2017/07/03/Angularjs学习笔记
<h2 id="angular">Angular</h2>
<p>angular主要致力于减轻前端人员开发ajax应用程序的痛苦</p>
<h2 id="mvc">MVC</h2>
<p>MVC核心概念:把管理数据的代码(model)、应用逻辑代码(controller)、向用户展示数据的代码(view)清晰的分离开。在angular应用中:视图就是DOM,控制器就是javascript类,模型数据则被存储在对象的属性中。</p>
<h2 id="数据绑定">数据绑定</h2>
<h3 id="单向数据绑定">单向数据绑定</h3>
<p>很多传统的模板系统数据绑定都是单向的,如下图:
<img src="https://wanls4583.github.io/images/posts/前端框架/2017-07-03-Angularjs学习笔记-1.jpg" alt="" /></p>
<p>它们将模板和数据合并起来加入到视图中去,如图表中所示。合并完成之后,从图中的流向可以看出,任何对数据模型或者相关内容的改变都不会自动反映到视图中去。而且用户对视图的任何改变也不会自动同步到数据模型中来。这意味着,开发者需要编写代码来保持视图与模板、模板与视图的同步,无疑增加了开发的工作量。</p>
<h3 id="双向数据绑定">双向数据绑定</h3>
<p>angularjs里的数据绑定模式为MVVM,即双向数据绑定,如下图:
<img src="https://wanls4583.github.io/images/posts/前端框架/2017-07-03-Angularjs学习笔记-2.jpg" alt="" /></p>
<p>双向数据绑定允许你把应用中的模型看成单一数据源。而视图始终是数据模型的一种展现形式。当模型改变时,视图就能反映这种改变,反之亦然。数据模型(model)与视图(view)组件的自动同步。</p>
<h2 id="controller">Controller</h2>
<h3 id="controller作用域问题">controller作用域问题</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-app="">
<div ng-controller="firstController">
<input type="text" value="" ng-model="name"/>
<div ng-controller="secondController">
<input type="text" value="" ng-model="name"/>
</div>
</div>
</div>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">firstController</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">$scope</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">secondController</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">$scope</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>ng-app=”“(默认模块)的情况下,控制器函数为全局函数,嵌套在里面的控制器的作用域优先级高于外层的,如果secondController 作用域没有name属性,则会沿着作用域链向上查找。</p>
<h3 id="ng-bind">ng-bind</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-controller="firstController">
<input type="text" value="" ng-model="name"/>
<input type="text" value="" ng-model="age"/>
<div ng-bind="name"></div>
{{name}}
<div ng-bind="age"></div>
{{age}}
</div>
</code></pre></div></div>
<p>ng-bind主要用来解决当angular加载过慢时,angular来不及解析页面,页面会显示{{name}}等表达式</p>
<h2 id="双向数据绑定原理applydigestwatch">双向数据绑定原理($apply、$digest、$watch)</h2>
<h3 id="watch">$watch</h3>
<p>$watch是一个scope函数,用于监听模型变化,当你的模型部分发生变化时它会通知你,我们可以在回调函数编写相应代码</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">firstController</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">data</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">name</span> <span class="p">:</span><span class="dl">'</span><span class="s1">李四</span><span class="dl">'</span><span class="p">,</span>
<span class="p">}</span>
<span class="c1">// 监听一个model,初始化是触发一次,以后每当model改变时都会触发 </span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">$watch</span><span class="p">(</span><span class="dl">'</span><span class="s1">name</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">newValue</span><span class="p">,</span><span class="nx">oldValue</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">watch_name</span><span class="dl">"</span><span class="p">)</span>
<span class="p">});</span>
<span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">张三1</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">$apply</span><span class="p">();</span>
<span class="p">},</span><span class="mi">1000</span><span class="p">)</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">$watch</span><span class="p">(</span><span class="dl">'</span><span class="s1">data</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">watch_data.name</span><span class="dl">"</span><span class="p">)</span>
<span class="p">},</span><span class="kc">true</span><span class="p">)</span>
<span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">data</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">李四1</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">$apply</span><span class="p">();</span>
<span class="p">},</span><span class="mi">1000</span><span class="p">)</span>
<span class="p">}</span>
</code></pre></div></div>
<p>可以看到,一次是controller初始化的时候触发的,另一次是定时器改变了model的值,如果我们在定时器中不改变name的值</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">setInterval</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">张三</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">$apply</span><span class="p">();</span>
<span class="p">},</span><span class="mi">1000</span><span class="p">)</span>
</code></pre></div></div>
<p>则定时器虽然会触发name属性的监听器,但是不会调用回调函数,因为name属性的值没有改变</p>
<h3 id="digest">$digest()</h3>
<p>$digest()是全局作用域$rootScope中的一个方法,用来进行脏检查。$digest循环开始后,它会触发每个watcher。这些watchers会检查scope中的当前model值是否和上一次计算得到的model值不同。如果不同,那么对应的回调函数会被执行。$digest循环一旦触发会执行两次。</p>
<h3 id="apply">$apply()</h3>
<p>当我们手动调用$apply()后,$apply()会调用$rootScope.$digest()进行脏值检查。</p>
<p>$apply()和$apply(function(){})的区别是,当你传入一个function到$apply()中的时候,这个function会被包装到一个try…catch块中,所以一旦有异常发生,该异常会被$exceptionHandler service处理。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$apply</span><span class="p">:</span> <span class="kd">function</span><span class="p">(</span><span class="nx">expr</span><span class="p">)</span> <span class="p">{</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nx">beginPhase</span><span class="p">(</span><span class="dl">'</span><span class="s1">$apply</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">$eval</span><span class="p">(</span><span class="nx">expr</span><span class="p">);</span><span class="c1">//解析函数字符串 </span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$exceptionHandler</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="p">}</span> <span class="k">finally</span> <span class="p">{</span>
<span class="nx">clearPhase</span><span class="p">();</span>
<span class="k">try</span> <span class="p">{</span>
<span class="nx">$rootScope</span><span class="p">.</span><span class="nx">$digest</span><span class="p">();</span>
<span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="nx">e</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$exceptionHandler</span><span class="p">(</span><span class="nx">e</span><span class="p">);</span>
<span class="k">throw</span> <span class="nx">e</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="angular双向数据绑定原理">angular双向数据绑定原理</h3>
<p>angular并不存在定时脏检测。angular对常用的dom事件,xhr事件等做了封装, 在里面触发进入angular的digest流程。在digest流程里面, 会从rootscope开始遍历, 检查所有的watcher。</p>
<p>谈起angular的脏检查机制(dirty-checking), 常见的误解就是认为: ng是定时轮询去检查model是否变更。
其实,ng只有在指定事件触发后,才进入$digest cycle:</p>
<ul>
<li>angular系统自带的DOM事件,譬如用户输入文本,点击按钮等。(ng-click)</li>
<li>XHR响应事件 ($http)</li>
<li>浏览器Location变更事件 ($location)</li>
<li>Timer事件($timeout, $interval)</li>
<li>执行$digest()或$apply()</li>
</ul>
<h2 id="angular模块">angular模块</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-app="myApp">
<div ng-controller="firstController">
{{name+a}}<!--a是无效的,不能使用全局变量-->
</div>
</div>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
<script type="text/javascript" src="app/index.js"></script>
</body>
</html>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,[]);</span>
<span class="nx">myApp</span><span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">;</span>
<span class="p">});</span>
<span class="kd">function</span> <span class="nx">firstController</span><span class="p">(</span><span class="nx">$scope</span><span class="p">){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">李四</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">a</span><span class="o">=</span><span class="mi">5</span><span class="p">;</span>
</code></pre></div></div>
<p>angular应用有一个默认的模块ng-app=”“,可以使用全局的函数作为控制器(但是不能使用全局变量),上面的输出结果为张三,如果我们指定了模块名称,则控制器会是myApp模块里的firstController,如果myApp模块里没有firstController,则是使用全局的firstController函数作为控制器。</p>
<p>使用模块的优点:可以将不同功能封装在不同的模块中,使用的时候直接依赖进来即可。</p>
<h2 id="provide">$provide</h2>
<p>$provide用来自定义服务</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,[],</span><span class="kd">function</span><span class="p">(</span><span class="nx">$provide</span><span class="p">){</span>
<span class="c1">// 自定义服务 </span>
<span class="nx">$provide</span><span class="p">.</span><span class="nx">provider</span><span class="p">(</span><span class="dl">'</span><span class="s1">CustomService</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">$get</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">{</span><span class="c1">//也可以返回基本类型 </span>
<span class="na">message</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">CustomService Message</span><span class="dl">'</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="c1">// 自定义工厂,相当于$provide.provider,只是少了调用$get方法的步骤 </span>
<span class="nx">$provide</span><span class="p">.</span><span class="nx">factory</span><span class="p">(</span><span class="dl">'</span><span class="s1">CustomFactory</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span><span class="c1">//myApp.factory() </span>
<span class="k">return</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">,</span><span class="mi">6</span><span class="p">,</span><span class="mi">7</span><span class="p">];</span><span class="c1">//也可以返回基本类型 </span>
<span class="p">});</span>
<span class="c1">// 自定义服务,相当于$provide.factory,不过只能返回对象 </span>
<span class="nx">$provide</span><span class="p">.</span><span class="nx">service</span><span class="p">(</span><span class="dl">'</span><span class="s1">CustomService2</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span><span class="c1">//myApp.service() </span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">aaa</span><span class="dl">'</span><span class="p">;</span><span class="c1">//无效返回,只可以返回对象 </span>
<span class="p">})</span>
<span class="p">});</span>
<span class="nx">myApp</span><span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">,</span><span class="nx">CustomService</span><span class="p">,</span><span class="nx">CustomFactory</span><span class="p">,</span><span class="nx">CustomService2</span><span class="p">){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">CustomService</span><span class="p">);</span><span class="c1">//Object {message: "CustomService Message"} </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">CustomFactory</span><span class="p">);</span><span class="c1">//[1, 2, 3, 4, 5, 6, 7] </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">CustomService2</span><span class="p">);</span><span class="c1">//Constructor {}, </span>
<span class="p">});</span>
<span class="cm">/*myApp.factory('CustomFactory',function(){
return [1,2,3,4,5,6,7];
});
myApp.service('CustomService2',function(){
return "aa";//无效返回,只可以返回对象
});*/</span>
</code></pre></div></div>
<p>在控制器里自动注入的服务,参数顺序可以是任意的</p>
<h2 id="多个controller里共享数据">多个controller里共享数据</h2>
<p>多个控制器里共享数据有两种方法:</p>
<ul>
<li>1.使用作用域链</li>
<li>2.使用自定义服务</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-app="myApp">
<div ng-controller="firstController">
first.data <input type="text" ng-model="data.name" />
first.Data <input type="text" ng-model="Data.message" />
<p>
first-name:{{data.name}}
</p>
<p>
first-message:{{Data.message}}
</p>
</div>
<div ng-controller="secondController">
<p>
second-name:{{data.name}}
</p>
<p>
second-message:{{Data.message}}
</p>
</div>
</div>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
<script type="text/javascript" src="app/index.js"></script>
</body>
</html>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,[])</span>
<span class="p">.</span><span class="nx">factory</span><span class="p">(</span><span class="dl">'</span><span class="s1">Data</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">message</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">共享的数据</span><span class="dl">'</span>
<span class="p">};</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">,</span><span class="nx">Data</span><span class="p">){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">data</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">name</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span>
<span class="p">};</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">Data</span> <span class="o">=</span> <span class="nx">Data</span><span class="p">;</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">secondController</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">$scope</span><span class="p">,</span><span class="nx">Data</span><span class="p">){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">data</span> <span class="o">=</span> <span class="nx">$scope</span><span class="p">.</span><span class="nx">$$prevSibling</span><span class="p">.</span><span class="nx">data</span><span class="p">;</span><span class="c1">//上一个控制器的作用域 </span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">Data</span> <span class="o">=</span> <span class="nx">Data</span><span class="p">;</span>
<span class="p">});</span>
</code></pre></div></div>
<h2 id="过滤器">过滤器</h2>
<p>数组过滤器可以自定义函数
{{ data.city | filter : checkName }}</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">$scope</span><span class="p">.</span><span class="nx">checkName</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">py</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="dl">'</span><span class="s1">h</span><span class="dl">'</span><span class="p">)</span> <span class="o">===</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>自定义过滤器</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-app="myApp">
<div ng-controller="firstController">
<ul>
<li ng-repeat="user in data | filterCity">
{{user.name}}
{{user.age}}
{{user.city}}
</li>
</ul>
</div>
</div>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[],</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$filterProvider</span><span class="p">,</span> <span class="nx">$provide</span><span class="p">,</span> <span class="nx">$controllerProvider</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$provide</span><span class="p">.</span><span class="nx">service</span><span class="p">(</span><span class="dl">'</span><span class="s1">Data</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">[</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">,</span>
<span class="na">age</span><span class="p">:</span> <span class="dl">'</span><span class="s1">20</span><span class="dl">'</span><span class="p">,</span>
<span class="na">city</span><span class="p">:</span> <span class="dl">'</span><span class="s1">上海</span><span class="dl">'</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">李四</span><span class="dl">'</span><span class="p">,</span>
<span class="na">age</span><span class="p">:</span> <span class="dl">'</span><span class="s1">30</span><span class="dl">'</span><span class="p">,</span>
<span class="na">city</span><span class="p">:</span> <span class="dl">'</span><span class="s1">北京</span><span class="dl">'</span>
<span class="p">}</span>
<span class="p">];</span>
<span class="p">});</span>
<span class="c1">//可以用$filterProvider注册过滤器 </span>
<span class="nx">$filterProvider</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="dl">'</span><span class="s1">filterAge</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">obj</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">newObj</span> <span class="o">=</span> <span class="p">[];</span>
<span class="nx">angular</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">age</span> <span class="o">></span> <span class="mi">20</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">newObj</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">o</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">newObj</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="nx">$controllerProvider</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">Data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">data</span> <span class="o">=</span> <span class="nx">Data</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">})</span>
<span class="c1">//用模块方法注册过滤器 </span>
<span class="p">.</span><span class="nx">filter</span><span class="p">(</span><span class="dl">'</span><span class="s1">filterCity</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span><span class="c1">//obj为要过滤的对象或者基本类型 </span>
<span class="kd">var</span> <span class="nx">temp</span> <span class="o">=</span> <span class="nx">arguments</span>
<span class="k">debugger</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">)</span>
<span class="kd">var</span> <span class="nx">newObj</span> <span class="o">=</span> <span class="p">[];</span>
<span class="nx">angular</span><span class="p">.</span><span class="nx">forEach</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">city</span> <span class="o">===</span> <span class="dl">'</span><span class="s1">上海</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">newObj</span><span class="p">.</span><span class="nx">push</span><span class="p">(</span><span class="nx">o</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="k">return</span> <span class="nx">newObj</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">})</span>
</code></pre></div></div>
<h2 id="显示和隐藏的依赖注入">显示和隐藏的依赖注入</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[],</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$filterProvider</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">$provide</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">$controllerProvider</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">,</span> <span class="nx">c</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">,</span> <span class="nx">c</span><span class="p">);</span>
<span class="p">}])</span>
<span class="p">.</span><span class="nx">factory</span><span class="p">(</span><span class="dl">'</span><span class="s1">CustomService</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$window</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
<span class="p">}])</span>
<span class="c1">// 隐示的依赖注入 </span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">,</span> <span class="nx">CustomService</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">CustomService</span><span class="p">);</span>
<span class="p">})</span>
<span class="c1">// 显示的依赖注入 </span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">secondController</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$scope</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">$filter</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">a</span><span class="p">,</span> <span class="nx">b</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">(</span><span class="dl">'</span><span class="s1">json</span><span class="dl">'</span><span class="p">)([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">]));</span>
<span class="p">}]);</span>
<span class="kd">function</span> <span class="nx">otherController</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">otherController</span><span class="p">.</span><span class="nx">$inject</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$scope</span><span class="dl">'</span><span class="p">];</span>
</code></pre></div></div>
<h2 id="指令">指令</h2>
<h3 id="渲染指令">渲染指令</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div ng-app="myApp">
<div>
<p>{{1+1}}</p>
<p ng-bind="1+1"></p>
<!-- xml校验写法 -->
<p ng:bind="1+1"></p>
<!-- html5校验写法 -->
<p data-ng-bind="1+1"></p>
<!-- xhtml校验写法 -->
<p x-ng-bind="1+1"></p>
<p ng-bind-template="{{1+1}}"></p>
<!-- $scope.cityArr = ['上海','北京','杭州'] -->
<ul ng-class="{red:status}" ng-init="cityArr = ['上海','北京','杭州','广州']">
<li ng-class-even="'偶数'" ng-class-odd="'奇数'" ng-repeat="city in cityArr" >
<span>
index:{{$index}}
</span>
<span>
first:{{$first}}
</span>
<span>
middle:{{$middle}}
</span>
<span>
last :{{$last}}
</span>
<span>
{{city}}
</span>
</li>
</ul>
<div ng-include="'other.html'">
</div>
<div ng-include src="'other.html'">
</div>
</div>
</div>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
</body>
</html>
</code></pre></div></div>
<h3 id="事件指令">事件指令</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-app="myApp">
<div ng-controller="firstController">
<!-- 注意:这里的函数必须执行 -->
<button ng-click="changeStatus($event)">切换状态</button>
</div>
</div>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[])</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">status</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">changeStatus</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// 通过element转换成 jquery对象 </span>
<span class="nx">angular</span><span class="p">.</span><span class="nx">element</span><span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">target</span><span class="p">).</span><span class="nx">html</span><span class="p">(</span><span class="dl">'</span><span class="s1">切换状态为:</span><span class="dl">'</span> <span class="o">+</span> <span class="nx">$scope</span><span class="p">.</span><span class="nx">status</span><span class="p">);</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">status</span> <span class="o">=</span> <span class="o">!</span><span class="nx">$scope</span><span class="p">.</span><span class="nx">status</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">})</span>
</code></pre></div></div>
<h3 id="节点指令">节点指令</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<style>
.red{
color:red;
}
.blue{
color:blue;
}
</style>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
<script type="text/javascript" src="app/index.js"></script>
</head>
<body>
<div ng-app="myApp">
<div ng-controller="firstController">
<div ng-style="{color:'red',fontSize:'40px'}">测试ng-style1</div>
<div ng-style="defaultStyle">测试ng-style2</div>
<div ng-class="{red:true}">测试ng-class1</div>
<div ng-init="status=true"></div>
<div ng-class="{red:status}">测试ng-class2</div>
<ul ng-init="cityArr = ['上海','北京','杭州','广州']">
<li ng-class-even="'red'" ng-class-odd="'blue'" ng-repeat="city in cityArr" >
{{city}}
</li>
</ul>
<div ng-show="false">
测试ng-show
</div>
<div ng-if="false">
测试ng-if
</div>
<!-- 普通src属性里的表达式会延迟解决,会先加载{{src}}字符串 ,解析后再加载正确图片-->
<img src="{{src}}"/>
<img ng-src="{{src}}"/>
<a ng-href="{{src}}">图片链接</a>
<div ng-init="myVar='google'"></div>
<!-- ng-switch-when里的表达式字符串不需要加引号,否则出错 -->
<div ng-switch="myVar">
<div ng-switch-when="google">
<h1>Google</h1>
</div>
<div ng-switch-when="taobao">
<h1>淘宝</h1>
</div>
<div ng-switch-default>
<h1>切换</h1>
</div>
</div>
<div ng-init="myVar1=1"></div>
<div ng-switch="myVar1">
<div ng-switch-when="1">
<h1>1</h1>
</div>
<div ng-switch-when="2">
<h1>2</h1>
</div>
</div>
</div>
</div>
</body>
</html>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[])</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">defaultStyle</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">color</span><span class="p">:</span><span class="dl">'</span><span class="s1">red</span><span class="dl">'</span><span class="p">,</span>
<span class="na">fontSize</span><span class="p">:</span><span class="dl">"</span><span class="s2">40px</span><span class="dl">"</span>
<span class="p">};</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">src</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">http://avatar.csdn.net/C/C/C/3_a409051987.jpg</span><span class="dl">'</span><span class="p">;</span>
<span class="p">})</span>
</code></pre></div></div>
<p>ng-if和ng-show的区别:ngIf 不会产生dom, ngShow 是代码里有,但通过 CSS 隐藏了。</p>
<h3 id="自定义指令">自定义指令</h3>
<h3 id="restricttemplatereplace属性">restrict、template、replace属性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="../../vendor/angular/angularjs.js"></script>
<script type="text/javascript" src="app/index.js"></script>
</head>
<body>
<div ng-app="myApp">
<directive-tag></directive-tag>
<div directive-tag></div>
<div class="directive-tag"></div>
<!-- directive:directive-tag -->
</div>
</body>
</html>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[],</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$compileProvider</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span> <span class="p">(</span><span class="nx">$compileProvider</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$compileProvider</span><span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">"</span><span class="s2">directiveTag</span><span class="dl">"</span><span class="p">,</span> <span class="kd">function</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span> <span class="p">:</span> <span class="dl">"</span><span class="s2">EACM</span><span class="dl">"</span><span class="p">,</span>
<span class="na">template</span> <span class="p">:</span> <span class="dl">"</span><span class="s2"><h1>自定义指令!</h1></span><span class="dl">"</span><span class="p">,</span>
<span class="na">replace</span> <span class="p">:</span> <span class="kc">true</span><span class="p">,</span><span class="c1">//设置true以后,会把指令标签删除 </span>
<span class="p">};</span>
<span class="p">})</span>
<span class="p">}])</span>
<span class="c1">//.directive('') </span>
</code></pre></div></div>
<p>restrict 值可以是以下几种:</p>
<ul>
<li>E 作为元素名使用</li>
<li>A 作为属性使用</li>
<li>C 作为类名使用</li>
<li>M 作为注释使用</li>
</ul>
<p>设置为M是在页面是没有效果,也不会替换,但是会运行compile方法</p>
<p>设置replace为true和false的区别:
<img src="https://wanls4583.github.io/images/posts/前端框架/2017-07-03-Angularjs学习笔记-3.jpg" alt="" /></p>
<h3 id="templateurl属性">templateUrl属性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-app="myApp">
<script type="text/ng-template" id="customTags2">
<div>
hello {{name}}
</div>
</script>
<div ng-controller="firstController">
<custom-tags></custom-tags>
<custom-tags2></custom-tags2>
</div>
</div>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[])</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">templateUrl</span><span class="p">:</span> <span class="dl">'</span><span class="s1">tmp/other.html</span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags2</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">templateUrl</span><span class="p">:</span> <span class="dl">'</span><span class="s1">customTags2</span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$scope</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}]);</span>
</code></pre></div></div>
<p>注意:tempate或者templateUrl里面的内容必须用一个标签包裹起来,不能是’‘<div>1</div><div>2</div>“或者”123”这种形式</p>
<p>tempateUrl里面可以是url或者是script type=”text/ng-template”的id</p>
<h3 id="transcludepriorityterminal属性">transclude、priority、terminal属性</h3>
<p>transclude用来保存原标签里原有的内容。</p>
<p>priority用来设置指令在模板中的执行顺序,顺序是相对于该元素上其他执行而言,指令默认的priority为0,一般不需要手动设置priority,像ng-repeat默认的priority为1000。</p>
<p>terminal用来设置是否以当前指令的权重为结束界限。如果设置为true,则节点权重小于当前指令的其他指令不会被执行。相同权重的会执行。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-app="myApp">
<div ng-controller="firstController">
<custom-tags>原始数据</custom-tags>
<div custom-tags2 custom-tags3>
</div>
</div>
</div>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[])</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">template</span><span class="p">:</span><span class="dl">'</span><span class="s1"><div>新数据 <span ng-transclude></span></div></span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">transclude</span><span class="p">:</span><span class="kc">true</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags2</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">template</span><span class="p">:</span><span class="dl">'</span><span class="s1"><div>2</div></span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">priority</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags3</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">template</span><span class="p">:</span><span class="dl">'</span><span class="s1"><div>3</div></span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">priority</span><span class="p">:</span> <span class="mi">0</span><span class="p">,</span>
<span class="c1">// 小于0的directive 都不会执行,否则还会继续解析customTags2里的template </span>
<span class="na">terminal</span><span class="p">:</span><span class="kc">true</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$scope</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}]);</span>
</code></pre></div></div>
<h3 id="compilelink属性">compile、link属性</h3>
<p>Angular指令编译三阶段:</p>
<ul>
<li>将html转换成dom,所有自定义的html标签必须符合html的格式</li>
<li>搜索匹配的directive,按照priority排序(默认优先级是0,ng-repeat为1000),并执行directive上的complie方法</li>
<li>执行directive上的link方法,进行scope绑定及事件绑定</li>
</ul>
<p><em>compile 函数:</em></p>
<p>使用compile函数可在ng创建原始dom实例以及创建scope实例之前以改变原始的dom(template element)。</p>
<p>可以应用于当需要生成多个element实例,只有一个template element的情况,ng-repeat就是一个最好的例子,它就在是compile函数阶段改变原始的dom生成多个原始dom节点,然后每个又生成element实例.因为compile只会运行一次,所以当你需要生成多个element实例的时候是可以提高性能的。template element以及相关的属性是做为参数传递给compile函数的,不过这时候scope是不能用的。</p>
<p><em>preLink:</em></p>
<p>pre-link函数,它能够保证在执行所有子指令的pre-link和post-link函数之前运行一些别的代码。pre-link函数可以在angular执行完compile函数之后,所有子指令的post-link函数将要执行之前运行一些业务代码。scope对象以及element实例将会做为参数传递给pre-link函数。</p>
<p><em>postLink:</em></p>
<p>post-link函数,它能够保证在执行所有子指令的pre-link和post-link函数之后运行一些别的代码,它和pre-link的执行顺序相反,被认为是最安全以及默认的编写业务逻辑代码的原因。scope对象以及element实例将会做为参数传递给post-link函数。</p>
<p>link函数负责在模型和视图之间进行同台关联,对于每个指令的每个实例,link函数都会执行一次。可以用来给元素进行事件的注册</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-controller="firstController">
<div ng-repeat="user in users" custom-tags="" custom-tags2>
</div>
</div>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">myApp</span> <span class="o">=</span> <span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[])</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">template</span> <span class="p">:</span> <span class="dl">'</span><span class="s1"><div>{{user.name}}</div></span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span> <span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="c1">//compile函数只运行一次 </span>
<span class="na">compile</span><span class="p">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">tElement</span><span class="p">,</span><span class="nx">tAttrs</span><span class="p">,</span><span class="nx">transclude</span><span class="p">){</span>
<span class="c1">// 编译阶段,这个阶段是没有scope作用域的 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags compile 编译阶段...</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">tElement</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="nx">angular</span><span class="p">.</span><span class="nx">element</span><span class="p">(</span><span class="dl">'</span><span class="s1"><div>点击次数:{{user.count}}</div></span><span class="dl">'</span><span class="p">));</span>
<span class="k">return</span> <span class="p">{</span>
<span class="c1">// 表示在编译阶段之后,指令连接到子元素之前运行 </span>
<span class="na">pre</span><span class="p">:</span><span class="kd">function</span> <span class="nx">preLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span><span class="nx">iElement</span><span class="p">,</span><span class="nx">iAttrs</span><span class="p">,</span><span class="nx">controller</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags preLink..</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">//在link里改变可以改变dom结构,但是不会再解析里面的表达式 </span>
<span class="nx">iElement</span><span class="p">.</span><span class="nx">append</span><span class="p">(</span><span class="nx">angular</span><span class="p">.</span><span class="nx">element</span><span class="p">(</span><span class="dl">'</span><span class="s1"><div>{{user.age}}</div></span><span class="dl">'</span><span class="p">));</span>
<span class="p">},</span>
<span class="c1">// 表示在所有子元素指令都连接之后才运行 </span>
<span class="na">post</span><span class="p">:</span><span class="kd">function</span> <span class="nx">postLink</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span><span class="nx">iElement</span><span class="p">,</span><span class="nx">iAttrs</span><span class="p">,</span><span class="nx">controller</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags all child directive link..</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">iElement</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">'</span><span class="s1">click</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">scope</span><span class="p">.</span><span class="nx">$apply</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">scope</span><span class="p">.</span><span class="nx">user</span><span class="p">.</span><span class="nx">count</span><span class="o">++</span><span class="p">;</span>
<span class="p">});</span>
<span class="p">})</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">// 可以直接返回 postLink </span>
<span class="c1">// return postLink function(){ </span>
<span class="c1">// console.log('compile return fun'); </span>
<span class="c1">//} </span>
<span class="p">},</span>
<span class="c1">// 此link表示的就是 postLink,如果compile有返回函数,则不会执行这个link </span>
<span class="na">link</span><span class="p">:</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行link</span><span class="dl">"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="c1">//这里template为空,同时定义customTags和customTags2不会报错 </span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags2</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span> <span class="p">:</span> <span class="kc">true</span><span class="p">,</span>
<span class="na">compile</span><span class="p">:</span><span class="kd">function</span><span class="p">(){</span>
<span class="c1">// 编译阶段... </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags2 compile 编译阶段...</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="p">{</span>
<span class="c1">// 表示在编译阶段之后,指令连接到子元素之前运行 </span>
<span class="na">pre</span><span class="p">:</span><span class="kd">function</span> <span class="nx">preLink</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags2 preLink..</span><span class="dl">'</span><span class="p">)</span>
<span class="p">},</span>
<span class="c1">// 表示在所有子元素指令都连接之后才运行 </span>
<span class="na">post</span><span class="p">:</span><span class="kd">function</span> <span class="nx">postLink</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags2 all child directive link..</span><span class="dl">'</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">customTags3</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="c1">// return postLink; </span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(){</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$scope</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">firstController控制器初始化</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">users</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{</span>
<span class="na">count</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span>
<span class="na">name</span><span class="p">:</span><span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">,</span>
<span class="na">age</span><span class="p">:</span><span class="mi">26</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="na">count</span><span class="p">:</span><span class="mi">0</span><span class="p">,</span>
<span class="na">name</span><span class="p">:</span><span class="dl">'</span><span class="s1">李四</span><span class="dl">'</span><span class="p">,</span>
<span class="na">age</span><span class="p">:</span><span class="mi">18</span>
<span class="p">},</span>
<span class="p">];</span>
<span class="p">}]);</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/前端框架/2017-07-03-Angularjs学习笔记-4.jpg" alt="" /></p>
<h3 id="controllercontrollerasrequire属性">controller、controllerAs、require属性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-app="myApp">
<div ng-controller="firstController">
<div book-list>
</div>
</div>
</div>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">globalScope</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[])</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">bookList</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">controller</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span><span class="c1">//必须是$scope,是注入的 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">bookList:</span><span class="dl">"</span><span class="o">+</span><span class="p">(</span><span class="nx">globalScope</span> <span class="o">==</span> <span class="nx">$scope</span><span class="p">));</span><span class="c1">//true </span>
<span class="k">this</span><span class="p">.</span><span class="nx">books</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">php</span><span class="dl">'</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">javascript</span><span class="dl">'</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">java</span><span class="dl">'</span>
<span class="p">}</span>
<span class="p">];</span>
<span class="kd">var</span> <span class="nx">that</span> <span class="o">=</span> <span class="k">this</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">addBook</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">$apply</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">that</span><span class="p">.</span><span class="nx">books</span><span class="p">.</span><span class="nx">push</span><span class="p">({</span>
<span class="na">name</span><span class="p">:</span><span class="dl">'</span><span class="s1">Angularjs</span><span class="dl">'</span>
<span class="p">})</span>
<span class="p">});</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="c1">//将会在scope一个属性为bookListController的对象,存储了该controller属性的数据 </span>
<span class="na">controllerAs</span><span class="p">:</span><span class="dl">'</span><span class="s1">bookListController</span><span class="dl">'</span><span class="p">,</span>
<span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1"><div><ul><li ng-repeat="book in bookListController.books">{{book.name}}</li></ul><book-add test-tag></book-add></div></span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span><span class="p">:</span><span class="kc">true</span><span class="p">,</span>
<span class="na">link</span><span class="p">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span><span class="nx">iElement</span><span class="p">,</span><span class="nx">iAttrs</span><span class="p">,</span><span class="nx">controller</span><span class="p">){</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">testTag</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span><span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">controller</span><span class="p">:</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">test</span><span class="o">=</span><span class="kd">function</span><span class="p">(){}</span>
<span class="p">},</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">bookAdd</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span><span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="c1">//自己没定义controller属性,去依赖别的controller属性,也可以去查找该元素的其他指令, </span>
<span class="c1">//此时就不需要用^号了,例如testTag </span>
<span class="na">require</span><span class="p">:</span><span class="dl">'</span><span class="s1">^bookList</span><span class="dl">'</span><span class="p">,</span>
<span class="na">template</span><span class="p">:</span><span class="dl">'</span><span class="s1"><button type="button">添加</button></span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span><span class="p">:</span><span class="kc">true</span><span class="p">,</span>
<span class="na">controller</span><span class="p">:</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">addBook</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">alert</span><span class="p">(</span><span class="dl">"</span><span class="s2">hehe</span><span class="dl">"</span><span class="p">)</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="c1">//将会在$scope里生成属性为bookAddController的对象,指向该指令的controller属性 </span>
<span class="na">controllerAs</span><span class="p">:</span><span class="dl">"</span><span class="s2">bookAddController</span><span class="dl">"</span><span class="p">,</span>
<span class="na">link</span><span class="p">:</span><span class="kd">function</span><span class="p">(</span><span class="nx">scope</span><span class="p">,</span><span class="nx">iElement</span><span class="p">,</span><span class="nx">iAttrs</span><span class="p">,</span><span class="nx">controller</span><span class="p">){</span>
<span class="c1">//定义了require属性,这里的控制器是require过来的控制器,会覆盖自己定义的控制器 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">bookadd:</span><span class="dl">"</span><span class="o">+</span><span class="p">(</span><span class="nx">globalScope</span> <span class="o">==</span> <span class="nx">scope</span><span class="p">));</span><span class="c1">//true </span>
<span class="c1">//iElement.on('click',controller.addBook); </span>
<span class="k">debugger</span><span class="p">;</span><span class="c1">//观察scope,请看下图 </span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$scope</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">lisong</span><span class="dl">"</span>
<span class="nx">globalScope</span> <span class="o">=</span> <span class="nx">$scope</span><span class="p">;</span>
<span class="p">}]);</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/前端框架/2017-07-03-Angularjs学习笔记-5.jpg" alt="" /></p>
<p>从上面的代码可知:</p>
<ul>
<li>默认情况下,控制器下的所有自定义指令都只有一个相同的作用域,那就是控制器的$scope</li>
<li>给自定义指令设置controllerAs属性,将会在$scope里生成一个对象,该对象执行了该指令的controller属性。</li>
<li>如果指定了require属性,则link的最后一个参数会指向其他指令的controller属性,而覆盖该指令定义的controller属性。</li>
</ul>
<p>require的参数:</p>
<ul>
<li>directiveName:通过驼峰命名指定了控制器应该带有带有那一天指令,默认会从同一个元素上查找指令</li>
<li>^directiveName:在父级查找指令</li>
<li>?directiveName:表示指令是可选的,如果找不到,不需要抛出异常</li>
</ul>
<h3 id="scope属性">scope属性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><div ng-controller="firstController">
{{
books
}}
<div book-list books="books" parent-books="books" parent-title="{{title}}">
</div>
</div>
</code></pre></div></div>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,</span> <span class="p">[])</span>
<span class="p">.</span><span class="nx">directive</span><span class="p">(</span><span class="dl">'</span><span class="s1">bookList</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">restrict</span><span class="p">:</span> <span class="dl">'</span><span class="s1">ECAM</span><span class="dl">'</span><span class="p">,</span>
<span class="na">controller</span><span class="p">:</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// &books </span>
<span class="c1">// $scope.books = $scope.a(); </span>
<span class="c1">// =books; </span>
<span class="c1">// $scope.books = $scope.b; </span>
<span class="c1">// $scope.b.push({name:'nodejs'}); </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">$scope</span><span class="p">.</span><span class="nx">c</span><span class="p">);</span>
<span class="p">},</span>
<span class="c1">// 创建一个有继承链的独立作用域 </span>
<span class="c1">// scope:true, </span>
<span class="c1">// 当为对象的时候也会创建一个独立的作用域 </span>
<span class="na">scope</span><span class="p">:{</span>
<span class="c1">// 将父元素books封装成一个a函数 </span>
<span class="c1">// a:'&books' </span>
<span class="c1">// 双向绑定 b = parentBooks属性对应的父作用域的表达式 </span>
<span class="c1">// b:'=parentBooks' </span>
<span class="c1">// 使用简单数据类型的方法 </span>
<span class="na">c</span><span class="p">:</span><span class="dl">'</span><span class="s1">@parentTitle</span><span class="dl">'</span>
<span class="p">},</span>
<span class="na">controllerAs</span><span class="p">:</span><span class="dl">'</span><span class="s1">bookListController</span><span class="dl">'</span><span class="p">,</span>
<span class="na">template</span><span class="p">:</span> <span class="dl">'</span><span class="s1"><div><ul><li ng-repeat="book in books">{{book.name}}</li></ul></div></span><span class="dl">'</span><span class="p">,</span>
<span class="na">replace</span><span class="p">:</span><span class="kc">true</span>
<span class="p">}</span>
<span class="p">})</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">$scope</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">$scope</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">$scope</span><span class="p">);</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">books</span> <span class="o">=</span> <span class="p">[</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">php</span><span class="dl">'</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">javascript</span><span class="dl">'</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="na">name</span><span class="p">:</span> <span class="dl">'</span><span class="s1">java</span><span class="dl">'</span>
<span class="p">}</span>
<span class="p">];</span>
<span class="nx">$scope</span><span class="p">.</span><span class="nx">title</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">张三</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}]);</span>
</code></pre></div></div>
<h2 id="模块里的constantvaluerun方法">模块里的constant、value、run方法</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">angular</span><span class="p">.</span><span class="nx">module</span><span class="p">(</span><span class="dl">'</span><span class="s1">myApp</span><span class="dl">'</span><span class="p">,[],[</span><span class="dl">'</span><span class="s1">$provide</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">$controllerProvider</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">$provide</span><span class="p">,</span><span class="nx">$controllerProvider</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">config1</span><span class="dl">'</span><span class="p">);</span>
<span class="c1">// $provide.factory </span>
<span class="c1">// $provide.service </span>
<span class="c1">// $provide.constant </span>
<span class="c1">// $provide.value; </span>
<span class="nx">$controllerProvider</span><span class="p">.</span><span class="nx">register</span><span class="p">(</span><span class="dl">"</span><span class="s2">secondController</span><span class="dl">"</span><span class="p">,[</span><span class="dl">'</span><span class="s1">APIKEY</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">vension</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">APIKEY</span><span class="p">,</span><span class="nx">vension</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">APIKEY</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vension</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">controller2</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}]);</span>
<span class="p">}])</span>
<span class="p">.</span><span class="nx">config</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">APIKEY</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">APIKEY</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">config2</span><span class="dl">'</span><span class="p">);</span>
<span class="p">})</span>
<span class="c1">// 在config之后controller等其他服务之前。。 </span>
<span class="p">.</span><span class="nx">run</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">run</span><span class="dl">'</span><span class="p">);</span>
<span class="p">})</span>
<span class="c1">// 它可以注入任何方法 </span>
<span class="p">.</span><span class="nx">constant</span><span class="p">(</span><span class="dl">'</span><span class="s1">APIKEY</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">xxxx</span><span class="dl">'</span><span class="p">)</span>
<span class="c1">// 只能注入controller...service factory </span>
<span class="p">.</span><span class="nx">value</span><span class="p">(</span><span class="dl">'</span><span class="s1">vension</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">1.0.0</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">controller</span><span class="p">(</span><span class="dl">'</span><span class="s1">firstController</span><span class="dl">'</span><span class="p">,[</span><span class="dl">'</span><span class="s1">APIKEY</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">vension</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">APIKEY</span><span class="p">,</span><span class="nx">vension</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">APIKEY</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">vension</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">controller1</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}]);</span>
</code></pre></div></div>
<h2 id="表达验证">表达验证</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><form name="myForm" action="kittencup.php" class="container form-horizontal">
<div class="form-group" ng-class="{'has-error':myForm.username.$dirty && myForm.username.$invalid}">
<label class="col-sm-2 control-label">用户名</label>
<div class="col-sm-10">
<input type="text" autocomplete="off" name="username" ng-pattern="/^[a-zA-Z]{1}/" ng-required="true" ng-minlength="5" ng-maxlength="10" ng-model="username" class="form-control" placeholder="用户名">
<div ng-show="myForm.username.$dirty && myForm.username.$error.maxlength" class="alert alert-danger help-block">
用户名长度不能超过10位
</div>
<div ng-show="myForm.username.$dirty && myForm.username.$error.minlength" class="alert alert-danger help-block">
用户名长度不能小于5位
</div>
<div ng-show="myForm.username.$dirty && myForm.username.$error.pattern" class="alert alert-danger help-block">
用户名必须已英文字母开始
</div>
<div>用户名:{{username}}</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default" ng-disabled="myForm.$invalid || data.hobbies === undefined || data.hobbies.length === 0">注册</button>
<button type="reset" class="btn btn-default" ng-click="reset()">重置</button>
</div>
</div>
</form>
</code></pre></div></div>
less中文示例教程
2017-07-03T06:00:30+00:00
https://blog.lisong.hn.cn/css/2017/07/03/less中文示例教程
<h2 id="一变量">一.变量</h2>
<h3 id="1value变量">1.value变量</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">//</span> <span class="nt">Variables</span>
<span class="k">@link-color</span><span class="p">:</span> <span class="m">#428bca</span><span class="p">;</span> <span class="o">//</span> <span class="nt">sea</span> <span class="nt">blue</span>
<span class="k">@link-color-hover</span><span class="p">:</span> <span class="n">darken</span><span class="p">(</span><span class="err">@</span><span class="n">link-color</span><span class="p">,</span> <span class="m">10%</span><span class="p">);</span>
<span class="o">//</span> <span class="nt">用法</span>
<span class="nt">a</span><span class="o">,</span>
<span class="nc">.link</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="err">@</span><span class="n">link-color</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">a</span><span class="nd">:hover</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="err">@</span><span class="n">link-color-hover</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.widget</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="err">@</span><span class="n">link-color</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">a</span><span class="o">,</span>
<span class="nc">.link</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#428bca</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">a</span><span class="nd">:hover</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#3071a9</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.widget</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="m">#428bca</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="简单编译">简单编译:</h3>
<p>1.安装less
<img src="https://wanls4583.github.io/images/posts/CSS/2017-07-03-less中文示例教程-1.jpg" alt="" /></p>
<p>2.新建less.less
<img src="https://wanls4583.github.io/images/posts/CSS/2017-07-03-less中文示例教程-2.jpg" alt="" /></p>
<p>3.编译less.less
<img src="https://wanls4583.github.io/images/posts/CSS/2017-07-03-less中文示例教程-3.jpg" alt="" /></p>
<p>此时就生成了less.css
<img src="https://wanls4583.github.io/images/posts/CSS/2017-07-03-less中文示例教程-4.jpg" alt="" /></p>
<h3 id="2selector变量">2.selector变量</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">//</span> <span class="nt">Variables</span>
<span class="k">@mySelector</span><span class="p">:</span> <span class="n">banner</span><span class="p">;</span>
<span class="o">//</span> <span class="nt">Usage</span>
<span class="o">.@</span><span class="p">{</span><span class="err">mySelector</span><span class="p">}</span> <span class="p">{</span>
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">bold</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">40px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span> <span class="nb">auto</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.banner</span> <span class="p">{</span>
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">bold</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">40px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span> <span class="nb">auto</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="3url变量">3.url变量</h3>
<p>示例1
input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">//</span> <span class="nt">Variables</span>
<span class="k">@images</span><span class="p">:</span> <span class="s1">"../img"</span><span class="p">;</span>
<span class="o">//</span> <span class="nt">用法</span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#444</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="sx">url("@{images}/white-sand.png")</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">body</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#444</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="sx">url("../img/white-sand.png")</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="4import-statement导入语句变量">4.Import statement(导入语句)变量</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">//</span> <span class="nt">Variables</span>
<span class="k">@images</span><span class="p">:</span> <span class="s1">"../img"</span><span class="p">;</span>
<span class="k">@out</span><span class="p">:</span><span class="s1">"import"</span><span class="p">;</span>
<span class="k">@import</span> <span class="s1">"@{out}.less"</span><span class="p">;</span>
<span class="o">//</span> <span class="nt">用法</span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#444</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="sx">url("@{images}/white-sand.png")</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>import.less:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">//</span> <span class="nt">Variables</span>
<span class="k">@mySelector</span><span class="p">:</span> <span class="n">banner</span><span class="p">;</span>
<span class="o">//</span> <span class="nt">Usage</span>
<span class="o">.@</span><span class="p">{</span><span class="err">mySelector</span><span class="p">}</span> <span class="p">{</span>
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">bold</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">40px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span> <span class="nb">auto</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.banner</span> <span class="p">{</span>
<span class="nl">font-weight</span><span class="p">:</span> <span class="nb">bold</span><span class="p">;</span>
<span class="nl">line-height</span><span class="p">:</span> <span class="m">40px</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span> <span class="nb">auto</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">body</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#444</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="sx">url("../img/white-sand.png")</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="5属性变量">5.属性变量</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@property</span><span class="p">:</span> <span class="n">color</span><span class="p">;</span>
<span class="nc">.widget</span> <span class="p">{</span>
<span class="err">@{property</span><span class="p">}</span><span class="o">:</span> <span class="err">#0</span><span class="nt">ee</span><span class="o">;</span>
<span class="nt">background-</span><span class="o">@</span><span class="p">{</span><span class="err">property</span><span class="p">}</span><span class="o">:</span> <span class="err">#999</span><span class="o">;</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.widget</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#0ee</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="m">#999</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="6变量名变量">6.变量名变量</h3>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@fnord</span><span class="p">:</span> <span class="s1">"#fff"</span><span class="p">;</span>
<span class="k">@var</span><span class="p">:</span> <span class="s1">"fnord"</span><span class="p">;</span>
<span class="nc">.class1</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@@</span><span class="n">var</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="s1">"#fff"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="7变量懒加载lazy-loading">7.变量懒加载(Lazy Loading)</h3>
<p>官方解释:Variables are lazy loaded and do not have to be declared before being used(编译器在编译less文件时,会先解析所有的变量,所以可以先使用变量,稍后再定义)</p>
<p>示例1
input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.lazy-eval</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="err">@</span><span class="n">var</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@var</span><span class="p">:</span> <span class="err">@</span><span class="n">a</span><span class="p">;</span>
<span class="k">@a</span><span class="p">:</span> <span class="m">9%</span><span class="p">;</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.lazy-eval</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">9%</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.lazy-eval-scope</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="err">@</span><span class="n">var</span><span class="p">;</span>
<span class="err">@</span><span class="py">a</span><span class="p">:</span> <span class="m">9%</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@var</span><span class="p">:</span> <span class="err">@</span><span class="n">a</span><span class="p">;</span>
<span class="k">@a</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.lazy-eval</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">9%</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:@a的作用域</p>
<p>示例3</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@var</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nc">.class1</span> <span class="p">{</span>
<span class="err">@</span><span class="py">var</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="err">.class</span> <span class="err">{</span>
<span class="err">@</span><span class="py">var</span><span class="p">:</span> <span class="m">2</span><span class="p">;</span>
<span class="py">three</span><span class="p">:</span> <span class="err">@</span><span class="n">var</span><span class="p">;</span>
<span class="err">@</span><span class="py">var</span><span class="p">:</span> <span class="m">3</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">one</span><span class="o">:</span> <span class="k">@var</span><span class="p">;</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="py">one</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class1</span> <span class="nc">.class</span> <span class="p">{</span>
<span class="py">three</span><span class="p">:</span> <span class="m">3</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="8默认变量">8.默认变量</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@import</span> <span class="s1">"import.less"</span><span class="p">;</span>
<span class="k">@dark-color</span><span class="p">:</span><span class="no">green</span><span class="p">;</span>
<span class="nc">.class1</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@</span><span class="n">dark-color</span>
<span class="p">}</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@</span><span class="n">white-color</span>
<span class="p">}</span>
</code></pre></div></div>
<p>import.less</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@white-color: #fff;
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@dark-color</span><span class="p">:</span><span class="no">green</span><span class="p">;</span>
<span class="k">@import</span> <span class="s1">"import.less"</span><span class="p">;</span>
<span class="nc">.class1</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@</span><span class="n">dark-color</span>
<span class="p">}</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@</span><span class="n">white-color</span>
<span class="p">}</span>
</code></pre></div></div>
<p>import.less</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@dark-color: #000;
@white-color: #fff;
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:后面定义的会覆盖前面定义的</p>
<h2 id="二extend继承">二.Extend(继承)</h2>
<h3 id="1extend-attached-to-selector为选择器附加扩展">1.Extend attached to selector(为选择器附加扩展)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.big-division</span><span class="o">,</span>
<span class="nc">.big-bag</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.bag</span><span class="o">),</span>
<span class="nc">.big-bucket</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.bucket</span><span class="o">)</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span><span class="m">1px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.bag</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="m">#fff</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.bucket</span><span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span><span class="m">#000</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:被继承的类,可以定义在后面</p>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.bag</span><span class="o">,</span>
<span class="nc">.big-bag</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.bucket</span><span class="o">,</span>
<span class="nc">.big-bucket</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.big-division</span><span class="o">,</span>
<span class="nc">.big-bag</span><span class="o">,</span>
<span class="nc">.big-bucket</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">1px</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="2extend-inside-ruleset规则集内的扩展">2.Extend inside ruleset(规则集内的扩展)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">a</span><span class="nd">:hover</span><span class="o">,</span>
<span class="nc">.some-class</span> <span class="p">{</span>
<span class="err">&:extend(div</span> <span class="err">span);</span>
<span class="p">}</span>
<span class="nt">div</span> <span class="nt">span</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">div</span> <span class="nt">span</span><span class="o">,</span>
<span class="nt">a</span><span class="nd">:hover</span><span class="o">,</span>
<span class="nc">.some-class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">###</span> <span class="err">3</span><span class="nc">.Extending</span> <span class="nt">nested</span> <span class="nt">Selectors</span><span class="err">(</span><span class="nt">嵌套选择器中的扩展</span><span class="err">)</span>
<span class="nt">示例1</span>
<span class="nt">input</span><span class="o">:</span>
<span class="err">```</span><span class="nt">css</span>
<span class="nc">.bucket</span> <span class="p">{</span>
<span class="err">tr</span> <span class="err">{</span> <span class="err">//</span> <span class="err">nested</span> <span class="err">ruleset</span> <span class="err">with</span> <span class="err">target</span> <span class="err">selector</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nc">.some-class</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.bucket</span> <span class="nt">tr</span><span class="o">)</span> <span class="p">{}</span> <span class="o">//</span> <span class="nt">nested</span> <span class="nt">ruleset</span> <span class="nt">is</span> <span class="nt">recognized</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.bucket</span> <span class="nt">tr</span><span class="o">,</span>
<span class="nc">.some-class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.bucket</span> <span class="p">{</span>
<span class="err">tr</span> <span class="err">&</span> <span class="err">{</span> <span class="err">//</span> <span class="err">nested</span> <span class="err">ruleset</span> <span class="err">with</span> <span class="err">target</span> <span class="err">selector</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nc">.some-class</span><span class="nd">:extend</span><span class="o">(</span><span class="nt">tr</span> <span class="nc">.bucket</span><span class="o">)</span> <span class="p">{}</span> <span class="o">//</span> <span class="nt">nested</span> <span class="nt">ruleset</span> <span class="nt">is</span> <span class="nt">recognized</span>
</code></pre></div></div>
<p>注意:&代表父选择器</p>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">tr</span> <span class="nc">.bucket</span><span class="o">,</span>
<span class="nc">.some-class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="4exact-matching-with-extend扩展中的精确匹配">4.Exact Matching with Extend(扩展中的精确匹配)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.a.class</span><span class="o">,</span>
<span class="nc">.class.a</span><span class="o">,</span>
<span class="nc">.class</span> <span class="o">></span> <span class="nc">.a</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.test</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.class</span><span class="o">)</span> <span class="p">{}</span> <span class="o">//</span> <span class="nt">不会匹配上面的</span><span class="nc">.class</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.a.class</span><span class="o">,</span>
<span class="nc">.class.a</span><span class="o">,</span>
<span class="nc">.class</span> <span class="o">></span> <span class="nc">.a</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="nc">.class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.noStar</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.class</span><span class="o">)</span> <span class="p">{}</span> <span class="o">//</span> <span class="nt">不会匹配</span><span class="o">*</span><span class="nc">.class</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">*</span><span class="nc">.class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例3</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">link</span><span class="nd">:hover:visited</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.selector</span><span class="nd">:extend</span><span class="o">(</span><span class="nt">link</span><span class="nd">:visited:hover</span><span class="o">)</span> <span class="p">{}</span><span class="o">//</span><span class="nt">不会匹配上面的</span><span class="err">,</span><span class="nt">顺序不一样</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">link</span><span class="nd">:hover:visited</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="5nth-expressionnth表达式">5.nth expression(nth表达式)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:nth-child</span><span class="o">(</span><span class="err">1</span><span class="nt">n</span><span class="o">+</span><span class="err">3</span><span class="o">)</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.child</span><span class="nd">:extend</span><span class="o">(</span><span class="nd">:nth-child</span><span class="o">(</span><span class="err">1</span><span class="nt">n</span><span class="o">+</span><span class="err">3</span><span class="o">))</span> <span class="p">{}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:nth-child</span><span class="o">(</span><span class="err">1</span><span class="nt">n</span><span class="o">+</span><span class="err">3</span><span class="o">),</span>
<span class="nc">.child</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:nth-child</span><span class="o">(</span><span class="err">1</span><span class="nt">n</span><span class="o">+</span><span class="err">3</span><span class="o">)</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.child</span><span class="nd">:extend</span><span class="o">(</span><span class="nd">:nth-child</span><span class="o">(</span><span class="nt">n</span><span class="o">+</span><span class="err">3</span><span class="o">))</span> <span class="p">{}</span><span class="o">//</span><span class="nt">不会匹配</span><span class="nd">:nth-child</span><span class="o">(</span><span class="err">1</span><span class="nt">n</span><span class="o">+</span><span class="err">3</span><span class="o">)</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">:nth-child</span><span class="o">(</span><span class="err">1</span><span class="nt">n</span><span class="o">+</span><span class="err">3</span><span class="o">)</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例3</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span><span class="nt">title</span><span class="o">=</span><span class="nt">identifier</span><span class="o">]</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">[</span><span class="nt">title</span><span class="o">=</span><span class="s2">'identifier'</span><span class="o">]</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">[</span><span class="nt">title</span><span class="o">=</span><span class="s1">"identifier"</span><span class="o">]</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.noQuote</span><span class="nd">:extend</span><span class="o">([</span><span class="nt">title</span><span class="o">=</span><span class="nt">identifier</span><span class="o">])</span> <span class="p">{}</span>
<span class="nc">.singleQuote</span><span class="nd">:extend</span><span class="o">([</span><span class="nt">title</span><span class="o">=</span><span class="s2">'identifier'</span><span class="o">])</span> <span class="p">{}</span>
<span class="nc">.doubleQuote</span><span class="nd">:extend</span><span class="o">([</span><span class="nt">title</span><span class="o">=</span><span class="s1">"identifier"</span><span class="o">])</span> <span class="p">{}</span>
</code></pre></div></div>
<p>注意:选择器属性值带引号和不带引号效果是一样的</p>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span><span class="nt">title</span><span class="o">=</span><span class="nt">identifier</span><span class="o">],</span>
<span class="nc">.noQuote</span><span class="o">,</span>
<span class="nc">.singleQuote</span><span class="o">,</span>
<span class="nc">.doubleQuote</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">[</span><span class="nt">title</span><span class="o">=</span><span class="s2">'identifier'</span><span class="o">],</span>
<span class="nc">.noQuote</span><span class="o">,</span>
<span class="nc">.singleQuote</span><span class="o">,</span>
<span class="nc">.doubleQuote</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">[</span><span class="nt">title</span><span class="o">=</span><span class="s1">"identifier"</span><span class="o">],</span>
<span class="nc">.noQuote</span><span class="o">,</span>
<span class="nc">.singleQuote</span><span class="o">,</span>
<span class="nc">.doubleQuote</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="6extend-all">6.Extend “all”</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.a.b.test</span><span class="o">,</span>
<span class="nc">.test.c</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">orange</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.test</span> <span class="p">{</span>
<span class="err">&:hover</span> <span class="err">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nc">.replacement</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.test</span> <span class="nt">all</span><span class="o">)</span> <span class="p">{}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.a.b.test</span><span class="o">,</span>
<span class="nc">.test.c</span><span class="o">,</span>
<span class="nc">.a.b.replacement</span><span class="o">,</span>
<span class="nc">.replacement.c</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">orange</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.test</span><span class="nd">:hover</span><span class="o">,</span>
<span class="nc">.replacement</span><span class="nd">:hover</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="7selector-interpolation-with-extend扩展中的选择器插值">7.Selector Interpolation with Extend(扩展中的选择器插值)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@variable</span><span class="p">:</span> <span class="p">.</span><span class="n">bucket</span><span class="p">;</span>
<span class="o">@</span><span class="p">{</span><span class="err">variable</span><span class="p">}</span> <span class="p">{</span> <span class="err">//</span> <span class="err">interpolated</span> <span class="err">selector</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.some-class</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.bucket</span><span class="o">)</span> <span class="p">{}</span> <span class="o">//</span><span class="nt">上面的</span><span class="nc">.bucket是有变量补全的</span><span class="err">,</span><span class="nt">不会匹配</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.bucket</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.bucket</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.some-class</span><span class="nd">:extend</span><span class="o">(@</span><span class="p">{</span><span class="err">variable</span><span class="p">}</span><span class="o">)</span> <span class="p">{}</span> <span class="o">//</span> <span class="nt">interpolated</span> <span class="nt">selector</span> <span class="nt">matches</span> <span class="nt">nothing</span>
<span class="k">@variable</span><span class="p">:</span> <span class="p">.</span><span class="n">bucket</span><span class="p">;</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.bucket</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例3</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.bucket</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">@</span><span class="p">{</span><span class="err">variable</span><span class="p">}</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.bucket</span><span class="o">)</span> <span class="p">{}</span><span class="o">//</span><span class="nt">However</span><span class="o">,</span> <span class="nd">:extend</span> <span class="nt">attached</span> <span class="nt">to</span> <span class="nt">an</span> <span class="nt">interpolated</span> <span class="nt">selector</span> <span class="nt">works</span>
<span class="k">@variable</span><span class="p">:</span> <span class="p">.</span><span class="n">selector</span><span class="p">;</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.bucket</span><span class="o">,</span>
<span class="nc">.selector</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="8scoping--extend-inside-media作用域media内的扩展">8.Scoping / Extend Inside @media(作用域/@media内的扩展)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@media</span> <span class="n">print</span> <span class="p">{</span>
<span class="nc">.screenClass</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.selector</span><span class="o">)</span> <span class="p">{}</span> <span class="o">//</span> <span class="nt">extend</span> <span class="nt">inside</span> <span class="nt">media</span>
<span class="nc">.selector</span> <span class="p">{</span> <span class="err">//</span> <span class="err">this</span> <span class="err">will</span> <span class="err">be</span> <span class="err">matched</span> <span class="err">-</span> <span class="err">it</span> <span class="err">is</span> <span class="err">in</span> <span class="err">the</span> <span class="err">same</span> <span class="err">media</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nc">.selector</span> <span class="p">{</span> <span class="err">//</span> <span class="err">ruleset</span> <span class="err">on</span> <span class="err">top</span> <span class="err">of</span> <span class="err">style</span> <span class="err">sheet</span> <span class="err">-</span> <span class="err">extend</span> <span class="err">ignores</span> <span class="err">it</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@media</span> <span class="n">screen</span> <span class="p">{</span>
<span class="nc">.selector</span> <span class="p">{</span> <span class="err">//</span> <span class="err">ruleset</span> <span class="err">inside</span> <span class="err">another</span> <span class="err">media</span> <span class="err">-</span> <span class="err">extend</span> <span class="err">ignores</span> <span class="err">it</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@media</span> <span class="n">print</span> <span class="p">{</span>
<span class="nc">.selector</span><span class="o">,</span>
<span class="nc">.screenClass</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nc">.selector</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@media</span> <span class="n">screen</span> <span class="p">{</span>
<span class="nc">.selector</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:在媒体查询大括号里的继承只能继承该媒体查询里面的选择器</p>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@media</span> <span class="n">screen</span> <span class="p">{</span>
<span class="nc">.screenClass</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.selector</span><span class="o">)</span> <span class="p">{}</span> <span class="o">//</span> <span class="nt">extend</span> <span class="nt">inside</span> <span class="nt">media</span>
<span class="k">@media</span> <span class="p">(</span><span class="n">min-width</span><span class="p">:</span> <span class="m">1023px</span><span class="p">)</span> <span class="p">{</span>
<span class="nc">.selector</span> <span class="p">{</span> <span class="err">//</span> <span class="err">ruleset</span> <span class="err">inside</span> <span class="err">nested</span> <span class="err">media</span> <span class="err">-</span> <span class="err">extend</span> <span class="err">ignores</span> <span class="err">it</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@media</span> <span class="n">screen</span> <span class="p">{</span>
<span class="p">}</span>
<span class="k">@media</span> <span class="n">screen</span> <span class="n">and</span> <span class="p">(</span><span class="n">min-width</span><span class="p">:</span> <span class="m">1023px</span><span class="p">)</span> <span class="p">{</span>
<span class="nc">.selector</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:在媒体查询大括号里的继承不能继承同级的其他的媒体查询里的选择器</p>
<p>示例3</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@media</span> <span class="n">screen</span> <span class="p">{</span>
<span class="nc">.selector</span> <span class="p">{</span> <span class="c">/* ruleset inside nested media - top level extend works */</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@media</span> <span class="p">(</span><span class="n">min-width</span><span class="p">:</span> <span class="m">1023px</span><span class="p">)</span> <span class="p">{</span>
<span class="nc">.selector</span> <span class="p">{</span> <span class="c">/* ruleset inside nested media - top level extend works */</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nc">.topLevel</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.selector</span><span class="o">)</span> <span class="p">{}</span> <span class="c">/* top level extend matches everything */</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@media</span> <span class="n">screen</span> <span class="p">{</span>
<span class="nc">.selector</span><span class="o">,</span>
<span class="nc">.topLevel</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">@media</span> <span class="n">screen</span> <span class="n">and</span> <span class="p">(</span><span class="n">min-width</span><span class="p">:</span> <span class="m">1023px</span><span class="p">)</span> <span class="p">{</span>
<span class="nc">.selector</span><span class="o">,</span>
<span class="nc">.topLevel</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:全局的选择器可以继承媒体查询里面的选择器,并且会被加入到该媒体查询里面</p>
<h3 id="9duplication-detection重复检测">9.Duplication Detection(重复检测)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.alert-info</span><span class="o">,</span>
<span class="nc">.widget</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.alert</span><span class="nd">:extend</span><span class="o">(</span><span class="nc">.alert-info</span><span class="o">,</span> <span class="nc">.widget</span><span class="o">)</span> <span class="p">{}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.alert-info</span><span class="o">,</span>
<span class="nc">.widget</span><span class="o">,</span>
<span class="nc">.alert</span><span class="o">,</span>
<span class="nc">.alert</span> <span class="p">{</span><span class="c">/*生成了两个.alert*/</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="10classic-use-case-经典用例">10.Classic Use Case (经典用例)</h3>
<p>经典用于就是避免添加基础类。比如,如果你有</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.animal</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>如果你想有一个animal子类型,并且要重写背景颜色。那么你有两个选择,首先改变你的HTML</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Bear
</code></pre></div></div>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.animal</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.bear</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">brown</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>或者简化HTML,然后在你的less中使用extend,比如:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Bear
</code></pre></div></div>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.animal</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.bear</span> <span class="p">{</span>
<span class="err">&:extend(.animal);</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">brown</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="11reducing-css-size-css尺寸归并">11.Reducing CSS Size (CSS尺寸归并)</h3>
<p>Mixins会复制所有的属性到选择器中,这可能导致不必要的重复。因此你可以使用extend来代替mixin将你要用的属性移过去,这样就会生成更少的CSS。</p>
<p>mixin示例:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-inline-block</span><span class="o">()</span> <span class="p">{</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.thing1</span> <span class="p">{</span>
<span class="err">.my-inline-block;</span>
<span class="p">}</span>
<span class="nc">.thing2</span> <span class="p">{</span>
<span class="err">.my-inline-block;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>输出:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.thing1</span> <span class="p">{</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.thing2</span> <span class="p">{</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例 (用扩展):</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-inline-block</span> <span class="p">{</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.thing1</span> <span class="p">{</span>
<span class="err">&:extend(.my-inline-block);</span>
<span class="p">}</span>
<span class="nc">.thing2</span> <span class="p">{</span>
<span class="err">&:extend(.my-inline-block);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>输出:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-inline-block</span><span class="o">,</span>
<span class="nc">.thing1</span><span class="o">,</span>
<span class="nc">.thing2</span> <span class="p">{</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="12combining-styles--a-more-advanced-mixin-合并样式更高级的mixin">12.Combining Styles / a more advanced mixin (合并样式/更高级的mixin)</h3>
<p>另一个用例可以用作mixin的替代 – 因为mixin仅仅能用于简单的选择器,如果你的html中有两个不同的块,但是你需要为这两个块应用相同的样式,那么你可以使用extend来关联这两块。</p>
<p>示例:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">li</span><span class="nc">.list</span> <span class="o">></span> <span class="nt">a</span> <span class="p">{</span>
<span class="err">//</span> <span class="err">list</span> <span class="err">styles</span>
<span class="p">}</span>
<span class="nt">button</span><span class="nc">.list-style</span> <span class="p">{</span>
<span class="err">&:extend(li.list</span> <span class="err">></span> <span class="err">a);</span> <span class="err">//</span> <span class="err">使用相同的列表样式</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="三mixins">三.mixins</h2>
<h3 id="1mix-in-properties-from-existing-styles">1.”mix-in” properties from existing styles</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.a</span><span class="o">,</span> <span class="nf">#b</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.mixin-class</span> <span class="p">{</span>
<span class="err">.a();</span>
<span class="p">}</span>
<span class="nc">.mixin-id</span> <span class="p">{</span>
<span class="err">#b();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.a</span><span class="o">,</span>
<span class="nf">#b</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.mixin-class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.mixin-id</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="2not-outputting-the-mixin-不输出混合集">2.Not outputting the mixin (不输出混合集)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-mixin</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.my-other-mixin</span><span class="o">()</span> <span class="p">{</span><span class="err">//加上括号后,混合集就不会输出到编译好的样式中了</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class</span> <span class="p">{</span>
<span class="err">.my-mixin;</span>
<span class="err">.my-other-mixin;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-mixin</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="3selectors-in-mixins-带选择器的混合集">3.Selectors in mixins (带选择器的混合集)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-hover-mixin</span><span class="o">()</span> <span class="p">{</span>
<span class="err">&:hover</span> <span class="err">{</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nt">button</span> <span class="p">{</span>
<span class="err">.my-hover-mixin();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">button</span><span class="nd">:hover</span> <span class="p">{</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-hover-mixin</span> <span class="p">{</span>
<span class="err">&:hover</span> <span class="err">{</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nt">button</span> <span class="p">{</span>
<span class="err">.my-hover-mixin();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>ouput:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-hover-mixin</span><span class="nd">:hover</span> <span class="p">{</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">button</span><span class="nd">:hover</span> <span class="p">{</span>
<span class="nl">border</span><span class="p">:</span> <span class="m">1px</span> <span class="nb">solid</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="4namespaces-命名空间">4.Namespaces (命名空间)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#outer</span> <span class="p">{</span>
<span class="err">.inner</span> <span class="err">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nc">.c</span> <span class="p">{</span>
<span class="err">#outer</span> <span class="err">></span> <span class="err">.inner;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#outer</span> <span class="nc">.inner</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.c</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">//</span> <span class="nt">下面四种写法效果是一样的</span>
<span class="nf">#outer</span> <span class="o">></span> <span class="nc">.inner</span><span class="o">;</span>
<span class="nf">#outer</span> <span class="o">></span> <span class="nc">.inner</span><span class="o">();</span>
<span class="nf">#outer</span><span class="nc">.inner</span><span class="o">;</span>
<span class="nf">#outer</span><span class="nc">.inner</span><span class="o">();</span>
</code></pre></div></div>
<p>这种用法的效果相当于我们熟知的命名空间,你可以把混合集放到一个id选择器里面,这样可以确保它(这个混合集)不会跟其他的库冲突。</p>
<p>例如示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#my-library</span> <span class="p">{</span>
<span class="err">.my-mixin()</span> <span class="err">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="o">//</span> <span class="nt">可以这样调用</span>
<span class="nc">.class</span> <span class="p">{</span>
<span class="err">#my-library</span> <span class="err">></span> <span class="err">.my-mixin();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例3</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#outer</span> <span class="p">{</span>
<span class="err">&.inner</span> <span class="err">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nc">.c</span> <span class="p">{</span>
<span class="err">#outer</span> <span class="err">></span> <span class="err">.inner;//对于这种方式,上面的&对.c是无效的</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#outer</span><span class="nc">.inner</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.c</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="5the-important-keyword-important-关键字">5.The !important keyword (!important 关键字)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.foo</span> <span class="o">(</span><span class="k">@bg</span><span class="p">:</span> <span class="m">#f5f5f5</span><span class="p">,</span> <span class="err">@</span><span class="n">color</span><span class="p">:</span> <span class="m">#900</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">background</span><span class="p">:</span> <span class="err">@</span><span class="n">bg</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="err">@</span><span class="n">color</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.unimportant</span> <span class="p">{</span>
<span class="err">.foo(1);</span>
<span class="p">}</span>
<span class="nc">.important</span> <span class="p">{</span>
<span class="err">.foo(2)</span> <span class="err">!important;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.unimportant</span> <span class="p">{</span>
<span class="nl">background</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#900</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.important</span> <span class="p">{</span>
<span class="nl">background</span><span class="p">:</span> <span class="m">2</span> <span class="cp">!important</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#900</span> <span class="cp">!important</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="四parametric-mixins-带参数的混合">四.Parametric Mixins (带参数的混合)</h2>
<h3 id="1how-to-pass-arguments-to-mixins">1.How to pass arguments to mixins</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.wrap</span><span class="o">()</span> <span class="p">{</span><span class="err">//带括号后,混合集不会输出到编译好的样式表中</span>
<span class="nl">text-wrap</span><span class="p">:</span> <span class="n">wrap</span><span class="p">;</span>
<span class="nl">white-space</span><span class="p">:</span> <span class="n">-moz-pre-wrap</span><span class="p">;</span>
<span class="nl">white-space</span><span class="p">:</span> <span class="n">pre-wrap</span><span class="p">;</span>
<span class="nl">word-wrap</span><span class="p">:</span> <span class="n">break-word</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">pre</span> <span class="p">{</span> <span class="err">.wrap</span> <span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">pre</span> <span class="p">{</span>
<span class="nl">text-wrap</span><span class="p">:</span> <span class="n">wrap</span><span class="p">;</span>
<span class="nl">white-space</span><span class="p">:</span> <span class="n">-moz-pre-wrap</span><span class="p">;</span>
<span class="nl">white-space</span><span class="p">:</span> <span class="n">pre-wrap</span><span class="p">;</span>
<span class="nl">word-wrap</span><span class="p">:</span> <span class="n">break-word</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.border-radius</span><span class="o">(</span><span class="k">@radius</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">-webkit-border-radius</span><span class="p">:</span> <span class="err">@</span><span class="n">radius</span><span class="p">;</span>
<span class="nl">-moz-border-radius</span><span class="p">:</span> <span class="err">@</span><span class="n">radius</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span> <span class="err">@</span><span class="n">radius</span><span class="p">;</span>
<span class="p">}</span>
<span class="nf">#header</span> <span class="p">{</span>
<span class="err">.border-radius(4px);</span>
<span class="p">}</span>
<span class="nc">.button</span> <span class="p">{</span>
<span class="err">.border-radius(6px);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#header</span> <span class="p">{</span>
<span class="nl">-webkit-border-radius</span><span class="p">:</span> <span class="m">4px</span><span class="p">;</span>
<span class="nl">-moz-border-radius</span><span class="p">:</span> <span class="m">4px</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span> <span class="m">4px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.button</span> <span class="p">{</span>
<span class="nl">-webkit-border-radius</span><span class="p">:</span> <span class="m">6px</span><span class="p">;</span>
<span class="nl">-moz-border-radius</span><span class="p">:</span> <span class="m">6px</span><span class="p">;</span>
<span class="nl">border-radius</span><span class="p">:</span> <span class="m">6px</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="2mixins-with-multiple-parameters-带多个参数的mixins">2.Mixins With Multiple Parameters (带多个参数的mixins)</h3>
<p>多个参数可以用分号或者逗号分割。但是推荐使用分号分割。因为逗号符号有两个意思:它可以解释为mixins参数分隔符或者css列表分隔符。</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">(</span><span class="k">@color</span><span class="p">)</span> <span class="p">{</span>
<span class="py">color-1</span><span class="p">:</span> <span class="err">@</span><span class="n">color</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.mixin</span><span class="o">(</span><span class="k">@color</span><span class="p">;</span> <span class="k">@padding</span><span class="p">:</span><span class="m">2</span><span class="p">)</span> <span class="p">{</span>
<span class="py">color-2</span><span class="p">:</span> <span class="err">@</span><span class="n">color</span><span class="p">;</span>
<span class="py">padding-2</span><span class="p">:</span> <span class="err">@</span><span class="n">padding</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.mixin</span><span class="o">(</span><span class="k">@color</span><span class="p">;</span> <span class="k">@padding</span><span class="p">;</span> <span class="k">@margin</span><span class="p">:</span> <span class="m">2</span><span class="p">)</span> <span class="p">{</span>
<span class="py">color-3</span><span class="p">:</span> <span class="err">@</span><span class="n">color</span><span class="p">;</span>
<span class="py">padding-3</span><span class="p">:</span> <span class="err">@</span><span class="n">padding</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="err">@</span><span class="n">margin</span> <span class="err">@</span><span class="n">margin</span> <span class="err">@</span><span class="n">margin</span> <span class="err">@</span><span class="n">margin</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.some</span> <span class="nc">.selector</span> <span class="nt">div</span> <span class="p">{</span>
<span class="err">.mixin(#008000);</span>
<span class="p">}</span>
<span class="nc">.other</span><span class="p">{</span>
<span class="err">.mixin(#fff;#000);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.some</span> <span class="nc">.selector</span> <span class="nt">div</span> <span class="p">{</span>
<span class="py">color-1</span><span class="p">:</span> <span class="m">#008000</span><span class="p">;</span>
<span class="py">color-2</span><span class="p">:</span> <span class="m">#008000</span><span class="p">;</span>
<span class="py">padding-2</span><span class="p">:</span> <span class="m">2</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.other</span> <span class="p">{</span>
<span class="py">color-2</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>
<span class="py">padding-2</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
<span class="py">color-3</span><span class="p">:</span> <span class="m">#fff</span><span class="p">;</span>
<span class="py">padding-3</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">2</span> <span class="m">2</span> <span class="m">2</span> <span class="m">2</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="3named-parameters-命名参数">3.Named Parameters (命名参数)</h3>
<p>引用mixin时可以通过参数名称而不是参数的位置来为mixin提供参数值。任何参数都已通过它的名称来引用,这样就不必按照任意特定的顺序来使用参数</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">(</span><span class="k">@color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span> <span class="k">@margin</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span> <span class="k">@padding</span><span class="p">:</span> <span class="m">20px</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="err">@</span><span class="n">color</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="err">@</span><span class="n">margin</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="err">@</span><span class="n">padding</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class1</span> <span class="p">{</span>
<span class="err">.mixin(@</span><span class="nl">margin</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span> <span class="err">@</span><span class="nl">color</span><span class="p">:</span> <span class="m">#33acfe</span><span class="p">);</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="err">.mixin(#efca44;</span> <span class="err">@</span><span class="nl">padding</span><span class="p">:</span> <span class="m">40px</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#33acfe</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#efca44</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">40px</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="4the-arguments-variable-arguments-变量">4.The @arguments variable (@arguments 变量)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.box-shadow</span><span class="o">(</span><span class="k">@x</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span> <span class="k">@y</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span> <span class="k">@blur</span><span class="p">:</span> <span class="m">1px</span><span class="p">;</span> <span class="k">@color</span><span class="p">:</span> <span class="m">#000</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">-webkit-box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">arguments</span><span class="p">;</span>
<span class="nl">-moz-box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">arguments</span><span class="p">;</span>
<span class="nl">box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">arguments</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.big-block</span> <span class="p">{</span>
<span class="err">.box-shadow(2px;</span> <span class="err">5px);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.big-block</span> <span class="p">{</span>
<span class="nl">-webkit-box-shadow</span><span class="p">:</span> <span class="m">2px</span> <span class="m">5px</span> <span class="m">1px</span> <span class="m">#000</span><span class="p">;</span>
<span class="nl">-moz-box-shadow</span><span class="p">:</span> <span class="m">2px</span> <span class="m">5px</span> <span class="m">1px</span> <span class="m">#000</span><span class="p">;</span>
<span class="nl">box-shadow</span><span class="p">:</span> <span class="m">2px</span> <span class="m">5px</span> <span class="m">1px</span> <span class="m">#000</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="5advanced-arguments-and-the-rest-variable-高级参数和rest变量">5.Advanced arguments and the @rest variable (高级参数和@rest变量)</h3>
<p>如果你希望你的mixin接受数量不定的参数,你可以使用…。在变量名后面使用它,它会将这些参数分配给变量。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">.</span><span class="nx">mixin</span><span class="p">(...)</span> <span class="p">{</span> <span class="c1">// matches 0-N arguments</span>
<span class="p">.</span><span class="nx">mixin</span><span class="p">()</span> <span class="p">{</span> <span class="c1">// matches exactly 0 arguments</span>
<span class="p">.</span><span class="nx">mixin</span><span class="p">(@</span><span class="nd">a</span><span class="p">:</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span> <span class="c1">// matches 0-1 arguments</span>
<span class="p">.</span><span class="nx">mixin</span><span class="p">(@</span><span class="nd">a</span><span class="p">:</span> <span class="mi">1</span><span class="p">;</span> <span class="p">...)</span> <span class="p">{</span> <span class="c1">// matches 0-N arguments</span>
<span class="p">.</span><span class="nx">mixin</span><span class="p">(@</span><span class="nd">a</span><span class="p">;</span> <span class="p">...)</span> <span class="p">{</span> <span class="c1">// matches 1-N arguments</span>
</code></pre></div></div>
<p>此外:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">(</span><span class="k">@a</span><span class="p">;</span> <span class="k">@rest</span><span class="p">...)</span> <span class="p">{</span>
<span class="o">//</span> <span class="k">@rest</span> <span class="n">is</span> <span class="n">bound</span> <span class="n">to</span> <span class="n">arguments</span> <span class="n">after</span> <span class="err">@</span><span class="n">a</span>
<span class="p">//</span> <span class="err">@</span><span class="n">arguments</span> <span class="n">is</span> <span class="n">bound</span> <span class="n">to</span> <span class="n">all</span> <span class="n">arguments</span>
<span class="err">}</span>
</code></pre></div></div>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">(</span><span class="k">@a</span><span class="p">,...){</span>
<span class="nl">color</span><span class="p">:</span><span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.mixin</span><span class="o">(...)</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class1</span><span class="p">{</span>
<span class="err">.mixin(1);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2
input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.box-shadow</span><span class="o">(...)</span> <span class="p">{</span>
<span class="nl">-webkit-box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">arguments</span><span class="p">;</span>
<span class="nl">-moz-box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">arguments</span><span class="p">;</span>
<span class="nl">box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">arguments</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.box-shadow</span><span class="o">(</span><span class="k">@a</span><span class="p">,</span><span class="err">@</span><span class="n">rest</span><span class="p">...)</span> <span class="p">{</span>
<span class="nl">-webkit-box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">rest</span><span class="p">;</span>
<span class="nl">-moz-box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">rest</span><span class="p">;</span>
<span class="nl">box-shadow</span><span class="p">:</span> <span class="err">@</span><span class="n">rest</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.big-block</span> <span class="p">{</span>
<span class="err">.box-shadow(2px,5px,#fff);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.big-block</span> <span class="p">{</span>
<span class="nl">-webkit-box-shadow</span><span class="p">:</span> <span class="m">2px</span> <span class="m">5px</span> <span class="m">#fff</span><span class="p">;</span>
<span class="nl">-moz-box-shadow</span><span class="p">:</span> <span class="m">2px</span> <span class="m">5px</span> <span class="m">#fff</span><span class="p">;</span>
<span class="nl">box-shadow</span><span class="p">:</span> <span class="m">2px</span> <span class="m">5px</span> <span class="m">#fff</span><span class="p">;</span>
<span class="nl">-webkit-box-shadow</span><span class="p">:</span> <span class="m">5px</span> <span class="m">#fff</span><span class="p">;</span>
<span class="nl">-moz-box-shadow</span><span class="p">:</span> <span class="m">5px</span> <span class="m">#fff</span><span class="p">;</span>
<span class="nl">box-shadow</span><span class="p">:</span> <span class="m">5px</span> <span class="m">#fff</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="6pattern-matching-模式匹配">6.Pattern-matching (模式匹配)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">(</span><span class="nt">dark</span><span class="o">;</span> <span class="k">@color</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="n">darken</span><span class="p">(</span><span class="err">@</span><span class="n">color</span><span class="p">,</span> <span class="m">10%</span><span class="p">);</span>
<span class="p">}</span>
<span class="nc">.mixin</span><span class="o">(</span><span class="nt">light</span><span class="o">;</span> <span class="k">@color</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="n">lighten</span><span class="p">(</span><span class="err">@</span><span class="n">color</span><span class="p">,</span> <span class="m">10%</span><span class="p">);</span>
<span class="p">}</span>
<span class="nc">.mixin</span><span class="o">(</span><span class="k">@_</span><span class="p">;</span> <span class="k">@color</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">display</span><span class="p">:</span> <span class="nb">block</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@switch</span><span class="p">:</span> <span class="n">light</span><span class="p">;</span>
<span class="nc">.class</span> <span class="p">{</span>
<span class="err">.mixin(@switch;</span> <span class="err">#888);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#a2a2a2</span><span class="p">;</span>
<span class="nl">display</span><span class="p">:</span> <span class="nb">block</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="五mixins-as-functions-作为函数使用的混合">五.Mixins as Functions (作为函数使用的混合)</h2>
<h3 id="1从mixin中返回变量">1.从mixin中返回变量</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">()</span> <span class="p">{</span>
<span class="err">@</span><span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="err">@</span><span class="nl">height</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.caller</span> <span class="p">{</span>
<span class="err">.mixin();</span>
<span class="nl">width</span><span class="p">:</span> <span class="err">@</span><span class="n">width</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="err">@</span><span class="n">height</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.caller</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.average</span><span class="o">(</span><span class="k">@x</span><span class="p">,</span> <span class="err">@</span><span class="n">y</span><span class="p">)</span> <span class="p">{</span>
<span class="k">@average</span><span class="p">:</span> <span class="p">((</span><span class="err">@</span><span class="n">x</span> <span class="err">+</span> <span class="err">@</span><span class="n">y</span><span class="p">)</span> <span class="p">/</span> <span class="m">2</span><span class="p">);</span>
<span class="p">}</span>
<span class="nt">div</span> <span class="p">{</span>
<span class="err">.average(16px,</span> <span class="err">50px);</span> <span class="err">//</span> <span class="err">"call"</span> <span class="err">the</span> <span class="err">mixin</span>
<span class="nl">padding</span><span class="p">:</span> <span class="err">@</span><span class="n">average</span><span class="p">;</span> <span class="err">//</span> <span class="err">use</span> <span class="err">its</span> <span class="err">"return"</span> <span class="err">value</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">div</span> <span class="p">{</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">33px</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>直接定义在调用者作用域内的变量不能被重写。然而,定义在调用者父级作用域内的变量是不是受保护的,将被重写:</p>
<p>示例3</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">()</span> <span class="p">{</span>
<span class="err">@</span><span class="nl">size</span><span class="p">:</span> <span class="n">in-mixin</span><span class="p">;</span>
<span class="err">@</span><span class="py">definedOnlyInMixin</span><span class="p">:</span> <span class="n">in-mixin</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class</span> <span class="p">{</span>
<span class="err">@</span><span class="py">definedOnlyInMixin</span><span class="p">:</span><span class="n">in-class</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="err">@</span><span class="n">size</span> <span class="err">@</span><span class="n">definedOnlyInMixin</span><span class="p">;</span>
<span class="err">.mixin();</span>
<span class="p">}</span>
<span class="k">@size</span><span class="p">:</span> <span class="n">globaly-defined-value</span><span class="p">;</span> <span class="o">//</span> <span class="nt">调用者父级作用域</span> <span class="nt">-</span> <span class="nt">不受保护</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class</span> <span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="n">in-mixin</span> <span class="n">in-class</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>最后,定义在mixin中的mixin同样可以作为返回值:</p>
<p>示例4</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.unlock</span><span class="o">(</span><span class="k">@value</span><span class="p">)</span> <span class="p">{</span> <span class="o">//</span> <span class="nt">外层的</span> <span class="nt">mixin</span>
<span class="nc">.doSomething</span><span class="o">()</span> <span class="p">{</span> <span class="err">//</span> <span class="err">被嵌套的</span> <span class="err">mixin</span>
<span class="py">declaration</span><span class="p">:</span> <span class="err">@</span><span class="n">value</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nf">#namespace</span> <span class="p">{</span>
<span class="err">.unlock(5);</span> <span class="err">//</span> <span class="err">unlock</span> <span class="err">doSomething</span> <span class="err">mixin</span>
<span class="err">.doSomething();</span> <span class="err">//嵌套混入被复制到这里,并可用</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#namespace</span> <span class="p">{</span>
<span class="py">declaration</span><span class="p">:</span> <span class="m">5</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="六passing-rulesets-to-mixins-传递规则集给混合">六.Passing Rulesets to Mixins (传递规则集给混合)</h2>
<h3 id="1detached-ruleset分离规则集合">1.detached ruleset(分离规则集合)</h3>
<p>分离(detached)规则集合是一组CSS属性,嵌套的规则集合,媒体声明或是存储在一个变量中的任何其他东西。你可以将其包含到一个规则集合或其他结构中,它的所有属性将被复制在那里。你也可以使用它作为一个mixin参数,并传递它周围的其他任何变量。</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">//</span> <span class="nt">声明</span> <span class="nt">detached</span> <span class="nt">规则集合</span>
<span class="k">@detached-ruleset</span><span class="p">:</span> <span class="p">{</span> <span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span> <span class="p">}</span><span class="o">;</span>
<span class="o">//</span> <span class="nt">使用</span> <span class="nt">detached</span> <span class="nt">规则集合</span>
<span class="nc">.top</span> <span class="p">{</span>
<span class="err">@detached-ruleset();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.top</span> <span class="p">{</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:分离(detached)规则集合调用时,其后面的圆括号是必须的, @detached-ruleset; 这样调用是无效的。
当你希望定义一个mixin将一个媒体查询中的一个代码块或者一个浏览器不支持的类名抽象出来时很有用。规则集合可以传递规则集给mixin,所以该mixin会包装这些内容。比如:</p>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.desktop-and-old-ie</span><span class="o">(</span><span class="k">@rules</span><span class="p">)</span> <span class="p">{</span>
<span class="k">@media</span> <span class="n">screen</span> <span class="n">and</span> <span class="p">(</span><span class="n">min-width</span><span class="p">:</span> <span class="m">1200</span><span class="p">)</span> <span class="p">{</span> <span class="k">@rules</span><span class="p">();</span> <span class="p">}</span>
<span class="nt">html</span><span class="nc">.lt-ie9</span> <span class="o">&</span> <span class="p">{</span> <span class="err">@rules();</span> <span class="p">}</span>
<span class="p">}</span>
<span class="nt">header</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="err">.desktop-and-old-ie({</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span><span class="o">);</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">header</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@media</span> <span class="n">screen</span> <span class="n">and</span> <span class="p">(</span><span class="n">min-width</span><span class="p">:</span> <span class="m">1200</span><span class="p">)</span> <span class="p">{</span>
<span class="nt">header</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt">html</span><span class="nc">.lt-ie9</span> <span class="nt">header</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:如果有媒体查询,则生成的最终样式会放在媒体查询里面</p>
<p>示例3</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@my-ruleset</span><span class="p">:</span> <span class="p">{</span>
<span class="nc">.my-selector</span> <span class="p">{</span>
<span class="err">@media</span> <span class="err">tv</span> <span class="err">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="err">}</span><span class="o">;</span>
<span class="k">@media</span> <span class="p">(</span><span class="n">orientation</span><span class="p">:</span><span class="nb">portrait</span><span class="p">)</span> <span class="p">{</span>
<span class="k">@my-ruleset</span><span class="p">();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@media</span> <span class="p">(</span><span class="n">orientation</span><span class="p">:</span> <span class="nb">portrait</span><span class="p">)</span> <span class="n">and</span> <span class="n">tv</span> <span class="p">{</span>
<span class="nc">.my-selector</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>分离规则集合可以返回所有它的mixins给调用者,可以以同样的方式调用mixin。但是,它不会返回变量。</p>
<p>示例4</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">//</span> <span class="nt">带有mixin的分离规则集合</span>
<span class="k">@detached-ruleset</span><span class="p">:</span> <span class="p">{</span>
<span class="nc">.mixin</span><span class="o">()</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span><span class="o">;</span>
<span class="o">//</span> <span class="nt">调用分离规则集合</span>
<span class="nc">.caller</span> <span class="p">{</span>
<span class="err">@detached-ruleset();</span>
<span class="err">.mixin();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.caller</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例5</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@detached-ruleset</span><span class="p">:</span> <span class="p">{</span>
<span class="k">@color</span><span class="p">:</span><span class="no">blue</span><span class="p">;</span> <span class="o">//</span> <span class="nt">私有变量</span>
<span class="p">}</span><span class="o">;</span>
<span class="nc">.caller</span> <span class="p">{</span>
<span class="err">@detached-ruleset();</span>
<span class="nl">color</span><span class="p">:</span> <span class="err">@</span><span class="n">color</span><span class="p">;</span> <span class="err">//</span> <span class="err">语法错误</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="2scoping-作用域">2.Scoping (作用域)</h3>
<p>分离规则集合可以在它被 定义 和被 调用 的地方使用所有变量和混入。换句话说, 定义和调用的作用域对它都是有效的。如果这两个作用域包含相同的变量或混入,声明的作用域中的值优先。</p>
<p><em>1.Definition and Caller Scope Visibility (定义和调用者作用域的可见性)</em></p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@detached-ruleset</span><span class="p">:</span> <span class="p">{</span>
<span class="py">caller-variable</span><span class="p">:</span> <span class="err">@</span><span class="n">callerVariable</span><span class="p">;</span> <span class="err">//</span> <span class="err">这里变量是</span> <span class="err">undefined</span>
<span class="err">.callerMixin();</span> <span class="err">//</span> <span class="err">这里混合是</span> <span class="err">undefined</span>
<span class="p">}</span><span class="o">;</span>
<span class="nt">selector</span> <span class="p">{</span>
<span class="err">//</span> <span class="err">使用分离规则集合</span>
<span class="err">@detached-ruleset();</span>
<span class="err">//</span> <span class="err">需要在分离规则集合内定义变量和混合</span>
<span class="err">@</span><span class="py">callerVariable</span><span class="p">:</span> <span class="n">value</span><span class="p">;</span>
<span class="err">.callerMixin()</span> <span class="err">{</span>
<span class="py">variable</span><span class="p">:</span> <span class="n">declaration</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">selector</span> <span class="p">{</span>
<span class="py">caller-variable</span><span class="p">:</span> <span class="n">value</span><span class="p">;</span>
<span class="py">variable</span><span class="p">:</span> <span class="n">declaration</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@variable</span><span class="p">:</span> <span class="n">global</span><span class="p">;</span>
<span class="k">@detached-ruleset</span><span class="p">:</span> <span class="p">{</span>
<span class="o">//</span> <span class="nt">将使用全局变量</span><span class="err">,</span><span class="nt">因为他是访问形式定义的分离规则集合</span>
<span class="nt">variable</span><span class="o">:</span> <span class="k">@variable</span><span class="p">;</span>
<span class="p">}</span><span class="o">;</span>
<span class="nt">selector</span> <span class="p">{</span>
<span class="err">@detached-ruleset();</span>
<span class="err">@</span><span class="py">variable</span><span class="p">:</span> <span class="n">value</span><span class="p">;</span> <span class="err">//</span> <span class="err">在调用者内部定义的变量</span> <span class="err">-</span> <span class="err">将被忽略</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">selector</span> <span class="p">{</span>
<span class="py">variable</span><span class="p">:</span> <span class="n">global</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><em>2.Referencing Won’t Modify Detached Ruleset Scope (引用 不会 修改分离规则集合的作用域)</em></p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@detached-1</span><span class="p">:</span> <span class="p">{</span> <span class="py">scope-detached</span><span class="p">:</span> <span class="err">@</span><span class="n">one</span> <span class="err">@</span><span class="n">two</span><span class="p">;</span> <span class="p">}</span><span class="o">;</span>
<span class="nc">.one</span> <span class="p">{</span>
<span class="err">@</span><span class="py">one</span><span class="p">:</span> <span class="nb">visible</span><span class="p">;</span>
<span class="err">.two</span> <span class="err">{</span>
<span class="err">@</span><span class="py">detached-2</span><span class="p">:</span> <span class="err">@</span><span class="n">detached-1</span><span class="p">;</span> <span class="err">//</span> <span class="err">拷贝/重命名</span> <span class="err">规则集合</span>
<span class="err">@</span><span class="py">two</span><span class="p">:</span> <span class="nb">visible</span><span class="p">;</span> <span class="err">//</span> <span class="err">规则集合不能使用visible</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nc">.usePlace</span> <span class="p">{</span>
<span class="err">.one</span> <span class="err">></span> <span class="err">.two();</span>
<span class="err">@detached-2();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>ouput::
编译出错:@one未定义</p>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@detached-1</span><span class="p">:</span> <span class="p">{</span> <span class="py">scope-detached</span><span class="p">:</span> <span class="err">@</span><span class="n">one</span> <span class="err">@</span><span class="n">two</span><span class="p">;</span> <span class="p">}</span><span class="o">;</span>
<span class="nc">.one</span> <span class="p">{</span>
<span class="err">.two</span> <span class="err">{</span>
<span class="err">@</span><span class="py">one</span><span class="p">:</span> <span class="nb">visible</span><span class="p">;</span>
<span class="err">@</span><span class="py">detached-2</span><span class="p">:</span> <span class="err">@</span><span class="n">detached-1</span><span class="p">;</span> <span class="err">//</span> <span class="err">拷贝/重命名</span> <span class="err">规则集合</span>
<span class="err">@</span><span class="py">two</span><span class="p">:</span> <span class="nb">visible</span><span class="p">;</span> <span class="err">//</span> <span class="err">规则集合不能使用visible</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="nc">.usePlace</span> <span class="p">{</span>
<span class="err">.one</span> <span class="err">></span> <span class="err">.two();</span>
<span class="err">@detached-2();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.usePlace</span> <span class="p">{</span>
<span class="py">scope-detached</span><span class="p">:</span> <span class="nb">visible</span> <span class="nb">visible</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><em>3.Unlocking Will Modify Detached Ruleset Scope (解锁 会 修改分离规则集合的作用域)</em>
示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nf">#space</span> <span class="p">{</span>
<span class="err">.importer1()</span> <span class="err">{</span>
<span class="err">@</span><span class="py">detached</span><span class="p">:</span> <span class="err">{</span> <span class="n">scope-detached</span><span class="p">:</span> <span class="err">@</span><span class="n">variable</span><span class="p">;</span> <span class="p">}</span><span class="o">;</span> <span class="o">//</span> <span class="nt">定义分离规则集合</span>
<span class="err">}</span>
<span class="err">}</span>
<span class="nc">.importer2</span><span class="o">()</span> <span class="p">{</span>
<span class="err">@</span><span class="py">variable</span><span class="p">:</span> <span class="n">value</span><span class="p">;</span> <span class="err">//</span> <span class="err">解锁分离规则集合能使用这个变量</span>
<span class="err">#space</span> <span class="err">></span> <span class="err">.importer1();</span> <span class="err">//</span> <span class="err">解锁/导入分离规则集合</span>
<span class="p">}</span>
<span class="nc">.usePlace</span> <span class="p">{</span>
<span class="err">.importer2();</span> <span class="err">//</span> <span class="err">第二次解锁/导入分离规则集合</span>
<span class="err">@detached();</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.usePlace</span> <span class="p">{</span>
<span class="py">scope-detached</span><span class="p">:</span> <span class="n">value</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="七import-directives-导入准则">七.Import Directives (导入准则)</h2>
<h3 id="1import语句">1.@import语句</h3>
<p>在标准的CSS中,@import必须在所有其他类型的规则之前。但是Less.js不在乎你把@import语句放在什么位置。</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@</span><span class="n">dark-color</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@import</span> <span class="s1">"import.less"</span><span class="p">;</span>
<span class="nt">import</span><span class="nc">.less</span><span class="o">:</span>
<span class="o">[</span><span class="nt">css</span><span class="o">]</span> <span class="nt">view</span> <span class="nt">plain</span> <span class="nt">copy</span>
<span class="k">@dark-color</span><span class="p">:</span><span class="m">#000</span><span class="p">;</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="2file-extensions-文件扩展名">2.File extensions (文件扩展名)</h2>
<p>@import语句会通过Less依赖文件扩展名的方式区别对待不同的文件:</p>
<ul>
<li>如果文件有一个.css扩展名,则将它作为CSS对象,同时@import语句保持不变(查看下面的inline选项)</li>
<li>如果有其他扩展名,则作为Less对象,然后导入它。</li>
<li>如果没有扩展名,则插入.less,然后将它作为Less文件导入包含进来。</li>
</ul>
<p>示例:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@import</span> <span class="s1">"foo"</span><span class="p">;</span> <span class="o">//</span> <span class="nt">foo</span><span class="nc">.less</span> <span class="nt">is</span> <span class="nt">imported</span>
<span class="k">@import</span> <span class="s1">"foo.less"</span><span class="p">;</span> <span class="o">//</span> <span class="nt">foo</span><span class="nc">.less</span> <span class="nt">is</span> <span class="nt">imported</span>
<span class="k">@import</span> <span class="s1">"foo.php"</span><span class="p">;</span> <span class="o">//</span> <span class="nt">foo</span><span class="nc">.php</span> <span class="nt">imported</span> <span class="nt">as</span> <span class="nt">a</span> <span class="nt">less</span> <span class="nt">file</span>
<span class="k">@import</span> <span class="s1">"foo.css"</span><span class="p">;</span> <span class="o">//</span> <span class="nt">statement</span> <span class="nt">left</span> <span class="nt">in</span> <span class="nt">place</span><span class="o">,</span> <span class="nt">as-is</span>
</code></pre></div></div>
<h2 id="八import-options-导入选项">八.Import Options (导入选项)</h2>
<p>Less提供了一系列的CSS扩展来让你使用@import更灵活的导入第三方CSS文件。</p>
<p>语法:@import (keyword) “filename”;</p>
<p>下面导入指令已经被实现了:</p>
<ul>
<li>reference:使用Less文件但不输出</li>
<li>inline:在输出中包含源文件但不加工它</li>
<li>less:将文件作为Less文件对象,无论是什么文件扩展名</li>
<li>css:将文件作为CSS文件对象,无论是什么文件扩展名</li>
<li>once:只包含文件一次(默认行为)</li>
<li>multiple:包含文件多次</li>
</ul>
<h3 id="1reference-引用">1.reference (引用)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@</span><span class="n">dark-color</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@import</span> <span class="p">(</span><span class="n">reference</span><span class="p">)</span> <span class="s1">"import.less"</span><span class="p">;</span>
<span class="nt">import</span><span class="nc">.less</span><span class="o">:</span>
<span class="o">[</span><span class="nt">css</span><span class="o">]</span> <span class="nt">view</span> <span class="nt">plain</span> <span class="nt">copy</span>
<span class="k">@dark-color</span><span class="p">:</span><span class="m">#000</span><span class="p">;</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="2inline">2.inline</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@</span><span class="n">dark-color</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@import</span> <span class="p">(</span><span class="nb">inline</span><span class="p">)</span> <span class="s1">"import.less"</span><span class="p">;</span>
</code></pre></div></div>
<p>import.less:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@dark-color</span><span class="p">:</span><span class="m">#000</span><span class="p">;</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@dark-color</span><span class="p">:</span><span class="m">#000</span><span class="p">;</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="3less">3.less</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="err">@</span><span class="n">dark-color</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@import</span> <span class="p">(</span><span class="n">less</span><span class="p">)</span> <span class="s1">"import.css"</span><span class="p">;</span>
</code></pre></div></div>
<p>import.less:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@dark-color</span><span class="p">:</span><span class="m">#000</span><span class="p">;</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#000</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="4css">4.css</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@import</span> <span class="p">(</span><span class="n">css</span><span class="p">)</span> <span class="s1">"import.less"</span><span class="p">;</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@import</span> <span class="s1">"import.less"</span><span class="p">;</span>
<span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="5once">5.once</h3>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@import</span> <span class="p">(</span><span class="nb">once</span><span class="p">)</span> <span class="s1">"foo.less"</span><span class="p">;</span>
<span class="k">@import</span> <span class="p">(</span><span class="nb">once</span><span class="p">)</span> <span class="s1">"foo.less"</span><span class="p">;</span> <span class="o">//</span> <span class="nt">this</span> <span class="nt">statement</span> <span class="nt">will</span> <span class="nt">be</span> <span class="nt">ignored</span>
</code></pre></div></div>
<h3 id="6multiple">6.multiple</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@import</span> <span class="p">(</span><span class="n">multiple</span><span class="p">)</span> <span class="s1">"import.less"</span><span class="p">;</span>
<span class="k">@import</span> <span class="p">(</span><span class="n">multiple</span><span class="p">)</span> <span class="s1">"import.less"</span><span class="p">;</span>
</code></pre></div></div>
<p>import.less:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class2</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="九mixin-guards带条件的mixin">九.Mixin Guards(带条件的Mixin)</h2>
<h3 id="1when关键字">1.when关键字</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span> <span class="o">(</span><span class="k">@a</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="n">lightness</span><span class="p">(</span><span class="err">@</span><span class="n">a</span><span class="p">)</span> <span class="err">>=</span> <span class="m">50%</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.mixin</span> <span class="o">(</span><span class="k">@a</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="n">lightness</span><span class="p">(</span><span class="err">@</span><span class="n">a</span><span class="p">)</span> <span class="err"><</span> <span class="m">50%</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.mixin</span> <span class="o">(</span><span class="k">@a</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="err">@</span><span class="n">a</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class1</span> <span class="p">{</span> <span class="err">.mixin(#ddd)</span> <span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span> <span class="err">.mixin(#555)</span> <span class="p">}</span>
</code></pre></div></div>
<p>ouput:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#ddd</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="nl">color</span><span class="p">:</span> <span class="m">#555</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="2guard-comparison-operators-guard中的比较运算符">2.Guard comparison operators (Guard中的比较运算符)</h3>
<p>guards中可用的比较运算符的完整列表为: >, >=, =, =<, <。</p>
<p>示例1
input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@media</span><span class="p">:</span> <span class="n">mobile</span><span class="p">;</span>
<span class="nc">.mixin</span> <span class="o">(</span><span class="k">@a</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="err">@</span><span class="n">media</span> <span class="err">=</span> <span class="n">mobile</span><span class="p">)</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span><span class="no">red</span><span class="p">;</span> <span class="p">}</span>
<span class="nc">.mixin</span> <span class="o">(</span><span class="k">@a</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="err">@</span><span class="n">media</span> <span class="err">=</span> <span class="n">desktop</span><span class="p">)</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span><span class="no">green</span><span class="p">;</span> <span class="p">}</span>
<span class="nc">.max</span> <span class="o">(</span><span class="k">@a</span><span class="p">;</span> <span class="k">@b</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="err">@</span><span class="n">a</span> <span class="err">></span> <span class="err">@</span><span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="nl">width</span><span class="p">:</span> <span class="err">@</span><span class="n">a</span> <span class="p">}</span>
<span class="nc">.max</span> <span class="o">(</span><span class="k">@a</span><span class="p">;</span> <span class="k">@b</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="err">@</span><span class="n">a</span> <span class="err"><</span> <span class="err">@</span><span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="nl">width</span><span class="p">:</span> <span class="err">@</span><span class="n">b</span> <span class="p">}</span>
<span class="nc">.class1</span><span class="p">{</span>
<span class="err">.mixin(mobile);</span>
<span class="p">}</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="err">.max(5,10);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">10</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="3guard-logical-operators-guard逻辑运算符">3.Guard logical operators (Guard逻辑运算符)</h3>
<p>使用and关键字来组合guards</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span> <span class="o">(</span><span class="k">@a</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="n">isnumber</span><span class="p">(</span><span class="err">@</span><span class="n">a</span><span class="p">))</span> <span class="n">and</span> <span class="p">(</span><span class="err">@</span><span class="n">a</span> <span class="err">></span> <span class="m">0</span><span class="p">)</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span><span class="no">red</span> <span class="p">}</span><span class="o">;</span>
<span class="nc">.class1</span><span class="p">{</span>
<span class="err">.mixin(1);</span>
<span class="p">}</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="err">.mixin(0);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>ouput:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>通过用逗号 , 分隔guards来模仿 or 运算符</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span> <span class="o">(</span><span class="k">@a</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="n">isnumber</span><span class="p">(</span><span class="err">@</span><span class="n">a</span><span class="p">))</span> <span class="p">,</span> <span class="p">(</span><span class="err">@</span><span class="n">a</span> <span class="err">></span> <span class="m">0</span><span class="p">)</span> <span class="p">{</span> <span class="nl">color</span><span class="p">:</span><span class="no">red</span> <span class="p">}</span><span class="o">;</span>
<span class="nc">.class1</span><span class="p">{</span>
<span class="err">.mixin(1);</span>
<span class="p">}</span>
<span class="nc">.class2</span><span class="p">{</span>
<span class="err">.mixin(0);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.class1</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.class2</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="4type-checking-functions-类型检查函数">4.Type checking functions (类型检查函数)</h3>
<p>下面是一些基本的类型检查函数:</p>
<ul>
<li>iscolor</li>
<li>isnumber</li>
<li>isstring</li>
<li>iskeyword</li>
<li>isurl</li>
</ul>
<p>如果你想检查一个值除了数字是否是一个特定的单位,你可以使用下列方法之一:</p>
<ul>
<li>ispixel</li>
<li>ispercentage</li>
<li>isem</li>
<li>isunit</li>
</ul>
<h2 id="十css-guardscss-约束">十.CSS Guards(css 约束)</h2>
<p>约束也适用于CSS选择器,这是一个声明mixin的语法糖,会立即调用它。</p>
<p>例如,在1.5.0之前你不得不这样做。</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.my-optional-style</span><span class="o">()</span> <span class="nt">when</span> <span class="o">(</span><span class="k">@my-option</span> <span class="err">=</span> <span class="n">true</span><span class="p">)</span> <span class="p">{</span>
<span class="nt">button</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nc">.my-optional-style</span><span class="o">();</span>
</code></pre></div></div>
<p>现在你可以直接在样式上编写约束。</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">button</span> <span class="nt">when</span> <span class="o">(</span><span class="k">@my-option</span> <span class="err">=</span> <span class="n">true</span><span class="p">)</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@my-option</span> <span class="p">:</span> <span class="n">true</span><span class="p">;</span>
<span class="nt">output</span><span class="o">:</span>
<span class="o">[</span><span class="nt">css</span><span class="o">]</span> <span class="nt">view</span> <span class="nt">plain</span> <span class="nt">copy</span>
<span class="nt">button</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>你还可以通过与&特性结合实现’if’类型的语句,从而允许组合多个约束。</p>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">button</span><span class="p">{</span>
<span class="err">&</span> <span class="err">when</span> <span class="err">(@my-option</span> <span class="err">=</span> <span class="err">true)</span> <span class="err">{</span>
<span class="err">&{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">white</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="o">&</span> <span class="nt">when</span> <span class="o">(</span><span class="k">@my-option</span> <span class="err">=</span> <span class="n">false</span><span class="p">)</span> <span class="p">{</span>
<span class="o">&</span><span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="k">@my-option</span><span class="p">:</span><span class="n">false</span><span class="p">;</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">button</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="十一loops-循环">十一.Loops (循环)</h2>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.generate-columns</span><span class="o">(</span><span class="err">4</span><span class="o">);</span>
<span class="nc">.generate-columns</span><span class="o">(</span><span class="k">@n</span><span class="p">,</span> <span class="err">@</span><span class="n">i</span><span class="p">:</span> <span class="m">1</span><span class="p">)</span> <span class="n">when</span> <span class="p">(</span><span class="err">@</span><span class="n">i</span> <span class="err">=<</span> <span class="err">@</span><span class="n">n</span><span class="p">)</span> <span class="p">{</span>
<span class="nc">.column-</span><span class="o">@</span><span class="p">{</span><span class="err">i</span><span class="p">}</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="p">(</span><span class="err">@</span><span class="n">i</span> <span class="err">*</span> <span class="m">100%</span> <span class="p">/</span> <span class="err">@</span><span class="n">n</span><span class="p">);</span>
<span class="p">}</span>
<span class="nc">.generate-columns</span><span class="o">(</span><span class="k">@n</span><span class="p">,</span> <span class="p">(</span><span class="err">@</span><span class="n">i</span> <span class="err">+</span> <span class="m">1</span><span class="p">));</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.column-1</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">25%</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.column-2</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">50%</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.column-3</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">75%</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.column-4</span> <span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="十二merge-合并属性">十二.Merge (合并属性)</h2>
<h3 id="1comma-逗号">1.Comma (逗号)</h3>
<p>通过逗号添加属性的值。</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">()</span> <span class="p">{</span>
<span class="err">box-shadow+:</span> <span class="err">inset</span> <span class="err">0</span> <span class="err">0</span> <span class="err">10px</span> <span class="err">#555;</span>
<span class="p">}</span>
<span class="nc">.myclass</span> <span class="p">{</span>
<span class="err">.mixin();</span>
<span class="err">box-shadow+:</span> <span class="err">0</span> <span class="err">0</span> <span class="err">20px</span> <span class="err">black;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.myclass</span> <span class="p">{</span>
<span class="nl">box-shadow</span><span class="p">:</span> <span class="nb">inset</span> <span class="m">0</span> <span class="m">0</span> <span class="m">10px</span> <span class="m">#555</span><span class="p">,</span> <span class="m">0</span> <span class="m">0</span> <span class="m">20px</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="2space-作用域">2.Space (作用域)</h3>
<p>作用域内附加属性(用空格分隔)</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.mixin</span><span class="o">()</span> <span class="p">{</span>
<span class="err">transform+</span><span class="py">_</span><span class="p">:</span> <span class="n">scale</span><span class="p">(</span><span class="m">2</span><span class="p">);</span>
<span class="p">}</span>
<span class="nc">.myclass</span> <span class="p">{</span>
<span class="err">.mixin();</span>
<span class="err">transform+</span><span class="py">_</span><span class="p">:</span> <span class="n">rotate</span><span class="p">(</span><span class="m">15deg</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.myclass</span> <span class="p">{</span>
<span class="nl">transform</span><span class="p">:</span> <span class="n">scale</span><span class="p">(</span><span class="m">2</span><span class="p">)</span> <span class="n">rotate</span><span class="p">(</span><span class="m">15deg</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="十三parent-selectors-父级选择器">十三.Parent Selectors (父级选择器)</h2>
<p>& 运算符表示一个 嵌套规则 的父选择器,它在应用修改类或者应用伪类给现有选择器时最常用</p>
<h3 id="1single">1.single&</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.button</span> <span class="p">{</span>
<span class="err">&-ok</span> <span class="err">{</span>
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url("ok.png")</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">&</span><span class="nt">-cancel</span> <span class="p">{</span>
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url("cancel.png")</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">&</span><span class="nt">-custom</span> <span class="p">{</span>
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url("custom.png")</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.button-ok</span> <span class="p">{</span>
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url("ok.png")</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.button-cancel</span> <span class="p">{</span>
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url("cancel.png")</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.button-custom</span> <span class="p">{</span>
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url("custom.png")</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="2multiple--多个-">2.Multiple & (多个 &)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.link</span> <span class="p">{</span>
<span class="err">&</span> <span class="err">+</span> <span class="err">&</span> <span class="err">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">&</span> <span class="o">&</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">&&</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">&,</span> <span class="o">&</span><span class="nt">ish</span><span class="o">;</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">cyan</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.link</span> <span class="o">+</span> <span class="nc">.link</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.link</span> <span class="nc">.link</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.link.link</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.link</span><span class="o">,</span>
<span class="nc">.linkish</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">cyan</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>&代表所有的父选择器(而不只是最近的长辈):</p>
<p>示例2</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.grand</span> <span class="p">{</span>
<span class="err">.parent</span> <span class="err">{</span>
<span class="err">&</span> <span class="err">></span> <span class="err">&</span> <span class="err">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">&</span> <span class="o">&</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">&&</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="o">&,</span> <span class="o">&</span><span class="nt">ish</span><span class="o">;</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">cyan</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.grand</span> <span class="nc">.parent</span> <span class="o">></span> <span class="nc">.grand</span> <span class="nc">.parent</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.grand</span> <span class="nc">.parent</span> <span class="nc">.grand</span> <span class="nc">.parent</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.grand</span> <span class="nc">.parent.grand</span> <span class="nc">.parent</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.grand</span> <span class="nc">.parent</span><span class="o">,</span>
<span class="nc">.grand</span> <span class="nc">.parentish</span> <span class="p">{</span>
<span class="nl">color</span><span class="p">:</span> <span class="no">cyan</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="3changing-selector-order-改变选择器顺序">3.Changing selector order (改变选择器顺序)</h3>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.header</span> <span class="p">{</span>
<span class="err">.menu</span> <span class="err">{</span>
<span class="nl">border-radius</span><span class="p">:</span> <span class="m">5px</span><span class="p">;</span>
<span class="err">.no-borderradius</span> <span class="err">&</span> <span class="err">{</span>
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url('images/button-background.png')</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.header</span> <span class="nc">.menu</span> <span class="p">{</span>
<span class="nl">border-radius</span><span class="p">:</span> <span class="m">5px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.no-borderradius</span> <span class="nc">.header</span> <span class="nc">.menu</span> <span class="p">{</span>
<span class="nl">background-image</span><span class="p">:</span> <span class="sx">url('images/button-background.png')</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="4combinatorial-explosion">4.Combinatorial explosion</h3>
<p>&还可以用于生成一个逗号分割列表的所有可能的选择器排列:</p>
<p>示例1</p>
<p>input:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">p</span><span class="o">,</span> <span class="nt">a</span><span class="o">,</span> <span class="nt">ul</span><span class="o">,</span> <span class="nt">li</span> <span class="p">{</span>
<span class="nl">border-top</span><span class="p">:</span> <span class="m">2px</span> <span class="nb">dotted</span> <span class="m">#366</span><span class="p">;</span>
<span class="err">&</span> <span class="err">+</span> <span class="err">&</span> <span class="err">{</span>
<span class="nl">border-top</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">}</span>
</code></pre></div></div>
<p>output:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">p</span><span class="o">,</span>
<span class="nt">a</span><span class="o">,</span>
<span class="nt">ul</span><span class="o">,</span>
<span class="nt">li</span> <span class="p">{</span>
<span class="nl">border-top</span><span class="p">:</span> <span class="m">2px</span> <span class="nb">dotted</span> <span class="m">#366</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">p</span> <span class="o">+</span> <span class="nt">p</span><span class="o">,</span>
<span class="nt">p</span> <span class="o">+</span> <span class="nt">a</span><span class="o">,</span>
<span class="nt">p</span> <span class="o">+</span> <span class="nt">ul</span><span class="o">,</span>
<span class="nt">p</span> <span class="o">+</span> <span class="nt">li</span><span class="o">,</span>
<span class="nt">a</span> <span class="o">+</span> <span class="nt">p</span><span class="o">,</span>
<span class="nt">a</span> <span class="o">+</span> <span class="nt">a</span><span class="o">,</span>
<span class="nt">a</span> <span class="o">+</span> <span class="nt">ul</span><span class="o">,</span>
<span class="nt">a</span> <span class="o">+</span> <span class="nt">li</span><span class="o">,</span>
<span class="nt">ul</span> <span class="o">+</span> <span class="nt">p</span><span class="o">,</span>
<span class="nt">ul</span> <span class="o">+</span> <span class="nt">a</span><span class="o">,</span>
<span class="nt">ul</span> <span class="o">+</span> <span class="nt">ul</span><span class="o">,</span>
<span class="nt">ul</span> <span class="o">+</span> <span class="nt">li</span><span class="o">,</span>
<span class="nt">li</span> <span class="o">+</span> <span class="nt">p</span><span class="o">,</span>
<span class="nt">li</span> <span class="o">+</span> <span class="nt">a</span><span class="o">,</span>
<span class="nt">li</span> <span class="o">+</span> <span class="nt">ul</span><span class="o">,</span>
<span class="nt">li</span> <span class="o">+</span> <span class="nt">li</span> <span class="p">{</span>
<span class="nl">border-top</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
nodejs之require函数
2017-06-30T07:09:23+00:00
https://blog.lisong.hn.cn/nodejs/2017/06/30/nodejs之require函数
<p>nodejs的require函数有三种引入方式:</p>
<h2 id="1引入同目录下的包根据文件夹名称">1.引入同目录下的包(根据文件夹名称)</h2>
<p>示例:</p>
<p>node_require/somepackage/package.json:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="dl">"</span><span class="s2">name</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">somepackage</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">version</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">1.0.0</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">description</span><span class="dl">"</span><span class="p">:</span> <span class="dl">""</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">main</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">./dist/test.js</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">scripts</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">echo </span><span class="se">\"</span><span class="s2">Error: no test specified</span><span class="se">\"</span><span class="s2"> && exit 1</span><span class="dl">"</span>
<span class="p">},</span>
<span class="dl">"</span><span class="s2">author</span><span class="dl">"</span><span class="p">:</span> <span class="dl">""</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">license</span><span class="dl">"</span><span class="p">:</span> <span class="dl">"</span><span class="s2">ISC</span><span class="dl">"</span>
<span class="p">}</span>
</code></pre></div></div>
<p>注意:main属性指定了模块的入口文件,如果没有package.json文件,则入口文件默认为包根目录下的index.js文件</p>
<p>node_require/somepackage/dist/test.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">{</span><span class="na">name</span><span class="p">:</span><span class="dl">'</span><span class="s1">this is test.js</span><span class="dl">'</span><span class="p">};</span>
<span class="c1">//exports.a=a; </span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="o">=</span><span class="nx">a</span>
<span class="nx">node_require</span><span class="o">/</span><span class="nx">getModule1</span><span class="p">.</span><span class="nx">js</span><span class="err">:</span>
<span class="p">[</span><span class="nx">javascript</span><span class="p">]</span> <span class="nx">view</span> <span class="nx">plain</span> <span class="nx">copy</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">./somepackage</span><span class="dl">'</span><span class="p">)</span>
<span class="c1">//console.log(a.a.name); </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
</code></pre></div></div>
<p>注意:包名称前面需要加”./”
<img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-1.jpg" alt="" /></p>
<p>在命令行下运行:
<img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-2.jpg" alt="" /></p>
<h2 id="2引入同目录下node_modules目录下的包根据文件夹名称">2.引入同目录下node_modules目录下的包(根据文件夹名称)</h2>
<p>node_require\node_modules\somepackage\index.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">{</span><span class="na">name</span><span class="p">:</span><span class="dl">'</span><span class="s1">this is index.js</span><span class="dl">'</span><span class="p">};</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="o">=</span><span class="nx">a</span>
<span class="nx">node_require</span><span class="err">\</span><span class="nx">node_modules</span><span class="err">\</span><span class="nx">getModule2</span><span class="p">.</span><span class="nx">js</span>
<span class="p">[</span><span class="nx">javascript</span><span class="p">]</span> <span class="nx">view</span> <span class="nx">plain</span> <span class="nx">copy</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">somepackage</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
</code></pre></div></div>
<p>注意:这里直接写的包文件夹名称
<img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-3.jpg" alt="" /></p>
<p>在命令行下运行:
<img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-4.jpg" alt="" /></p>
<p>3.引入全局包</p>
<p>首先我们的设置全局环境变量,我这里的全局目录为C:\Users\Lisong\AppData\Roaming\npm\node_modules,所以设置环境变量NODE_PATH=C:\Users\Lisong\AppData\Roaming\npm\node_modules</p>
<p>示例:</p>
<p>C:\Users\Lisong\AppData\Roaming\npm\node_modules\somepackage\index.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">{</span><span class="na">name</span><span class="p">:</span><span class="dl">'</span><span class="s1">this is global_test</span><span class="dl">'</span><span class="p">};</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="o">=</span><span class="nx">a</span>
</code></pre></div></div>
<p>node_require\getModule3.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">somepackage</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-5.jpg" alt="" /></p>
<p>运行命令行:
<img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-6.jpg" alt="" /></p>
<p>此时,如果本地目录下也有somepackage包:</p>
<p>node_require\node_modules\somepackage\index.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">{</span><span class="na">name</span><span class="p">:</span><span class="dl">'</span><span class="s1">this is index.js</span><span class="dl">'</span><span class="p">};</span>
<span class="nx">module</span><span class="p">.</span><span class="nx">exports</span><span class="o">=</span><span class="nx">a</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-7.jpg" alt="" /></p>
<p>运行命令行:
<img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-8.jpg" alt="" /></p>
<p>可以看到,会优先使用本地包</p>
<p>最后说一下啊,require的作用域。nodejs的require函数是同步的(和seajs不一样),引入的时候会执行模块的所有代码,模块里定义的变量作用域值在模块内。</p>
<p>示例:</p>
<p>node_require\node_modules\somepackage\index.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="p">{</span><span class="na">name</span><span class="p">:</span><span class="dl">'</span><span class="s1">this is index.js</span><span class="dl">'</span><span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">index.js:</span><span class="dl">"</span><span class="o">+</span><span class="nx">a</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
</code></pre></div></div>
<p>node_require\getModule4.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">somepackage</span><span class="dl">'</span><span class="p">)</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-9.jpg" alt="" /></p>
<p>运行命令行:
<img src="https://wanls4583.github.io/images/posts/nodejs/2017-06-30-nodejs之require函数-10.jpg" alt="" /></p>
gulp结合seajs开发
2017-06-30T06:22:20+00:00
https://blog.lisong.hn.cn/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/2017/06/30/gulp结合seajs开发
<p>上一篇说了gruntjs结合seajs开发,这一节我们来说一下gulp结合seajs是怎么开发的。</p>
<p>其实gruntjs和gulp在前端开发中的作用是一样的,都是自动化项目的前端构建利器,那么它们有什么不一样呢?Grunt主要是以文件为媒介来运行它的工作流的,比如在Grunt中执行完一项任务后,会把结果写入到一个临时文件中,然后可以在这个临时文件内容的基础上执行其它任务,执行完成后又把结果写入到临时文件中,然后又以这个为基础继续执行其它任务…就这样反复下去。而在Gulp中,使用的是Nodejs中的stream(流),首先获取到需要的stream,然后可以通过stream的pipe()方法把流导入到你想要的地方,比如Gulp的插件中,经过插件处理后的流又可以继续导入到其他插件中,当然也可以把流写入到文件中。所以Gulp是以stream为媒介的,它不需要频繁的生成临时文件,这也是Gulp的速度比Grunt快的一个原因。再回到正题上来,gulp.src()方法正是用来获取流的,但要注意这个流里的内容不是原始的文件流,而是一个虚拟文件对象流(Vinyl files),这个虚拟文件对象中存储着原始文件的路径、文件名、内容等信息,这个我们暂时不用去深入理解,你只需简单的理解可以用这个方法来读取你需要操作的文件就行了</p>
<p>示例</p>
<p>package.json:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="dl">"</span><span class="s2">name</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">testGulp</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">version</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">0.1.0</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">dependencies</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">gulp</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~3.9.1</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">gulp-seajs-combo</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~1.2.3</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">gulp-uglify</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~2.0.1</span><span class="dl">"</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>gulpfile.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">gulp</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">'</span><span class="s1">gulp</span><span class="dl">'</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">seajsCombo</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span> <span class="dl">'</span><span class="s1">gulp-seajs-combo</span><span class="dl">'</span> <span class="p">);</span>
<span class="kd">var</span> <span class="nx">uglify</span> <span class="o">=</span> <span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">gulp-uglify</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">gulp</span><span class="p">.</span><span class="nx">task</span><span class="p">(</span><span class="dl">'</span><span class="s1">default</span><span class="dl">'</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">gulp</span><span class="p">.</span><span class="nx">src</span><span class="p">(</span><span class="dl">'</span><span class="s1">sea_modules/main.js</span><span class="dl">'</span><span class="p">)</span>
<span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">seajsCombo</span><span class="p">())</span>
<span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">uglify</span><span class="p">())</span>
<span class="p">.</span><span class="nx">pipe</span><span class="p">(</span><span class="nx">gulp</span><span class="p">.</span><span class="nx">dest</span><span class="p">(</span><span class="dl">'</span><span class="s1">.</span><span class="dl">'</span><span class="p">))</span>
<span class="p">});</span>
</code></pre></div></div>
<p>sea_modules/main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>sea_modules/a.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行a.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">})</span>
</code></pre></div></div>
<p>sea_modules/test.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">a.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">})</span>
</code></pre></div></div>
<p>sea.html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="sea.js"></script>
<script type="text/javascript">
seajs.use("main.js",function(){
console.log("执行入口模块回调函数");
})
</script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gulp结合seajs开发-1.jpg" alt="" /></p>
<p>在命令行下运行npm install安装package.json里的所有依赖,安装完后多了个node_modules文件夹
<img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gulp结合seajs开发-2.jpg" alt="" /></p>
<p>最后在命令行下执行gulp命令
<img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gulp结合seajs开发-3.jpg" alt="" /></p>
<p>此时,将会在gulp目录下生成我们想要的文件(合并压缩后的main.js)
<img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gulp结合seajs开发-4.jpg" alt="" /></p>
<p>运行sea.html测试结果:
<img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gulp结合seajs开发-5.jpg" alt="" /></p>
<p>可以看到,成功合并了文件。</p>
gruntjs结合seajs开发
2017-06-30T06:11:27+00:00
https://blog.lisong.hn.cn/%E6%9E%84%E5%BB%BA%E5%B7%A5%E5%85%B7/2017/06/30/gruntjs结合seajs开发
<blockquote>
<p>gruntjs是一款前端构建化工具,其可以帮我们做很多重复性的劳动,可以很大程度上提高前端开发的效率,下面用实例就来简单介绍下其配合seajs模块化框架是如何使用的。</p>
</blockquote>
<p>示例</p>
<p>1.首先你得安装nodejs,然后新建nodejs文件夹,当作项目的根目录,在其中新建package.json</p>
<p>package.json:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span>
<span class="dl">"</span><span class="s2">name</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">testGrunt</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">version</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">0.1.0</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">dependencies</span><span class="dl">"</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">"</span><span class="s2">grunt</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~1.0.1</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">grunt-cmd-concat</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~0.2.1</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">grunt-contrib-uglify</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~2.0.0</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">grunt-cmd-transport</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~0.5.1</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">grunt-mcopy</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~0.4.3</span><span class="dl">"</span><span class="p">,</span>
<span class="dl">"</span><span class="s2">grunt-contrib-clean</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">~0.6.0</span><span class="dl">"</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>2.打开命令行,进入nodejs目录,运行以下命令安装所有的依赖</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>npm install
</code></pre></div></div>
<p>此时将在nodejs目录下生成一个文件夹node_modules,里面包含了我们需要用的所有依赖
<img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gruntjs结合seajs开发-1.jpg" alt="" /></p>
<p>3.在nodejs目录下新建我们的测试页面</p>
<p>sea.html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="sea.js"></script>
<script type="text/javascript">
seajs.use("main",function(){
console.log("执行入口模块回调函数");
})
</script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p>注意:main为合并后的文件,,与sea.html同目录,该文件中的每个模块都必须要有id才能项目依赖,并且其入口模块的id必须为main</p>
<p>4.在nodejs目录下新建目录,用来存放项目的js模块,并且在该目录下新建main.js,a.js,test.js</p>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">test</span><span class="p">.</span><span class="nx">js</span><span class="err">:</span>
<span class="p">[</span><span class="nx">javascript</span><span class="p">]</span> <span class="nx">view</span> <span class="nx">plain</span> <span class="nx">copy</span>
<span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">a.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">})</span>
</code></pre></div></div>
<p>a.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">[</span><span class="nx">javascript</span><span class="p">]</span> <span class="nx">view</span> <span class="nx">plain</span> <span class="nx">copy</span>
<span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行a.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">})</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gruntjs结合seajs开发-2.jpg" alt="" /></p>
<p>5.把seajs框架文件sea.js拷贝到nodejs目录下,在nodejs目录下新建我们的grunt任务配置文件Gruntfile.js</p>
<p>Gruntfile.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">module</span><span class="p">.</span><span class="nx">exports</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">grunt</span><span class="p">)</span> <span class="p">{</span>
<span class="c1">// Project configuration. </span>
<span class="nx">grunt</span><span class="p">.</span><span class="nx">initConfig</span><span class="p">({</span>
<span class="na">pkg</span><span class="p">:</span> <span class="nx">grunt</span><span class="p">.</span><span class="nx">file</span><span class="p">.</span><span class="nx">readJSON</span><span class="p">(</span><span class="dl">'</span><span class="s1">package.json</span><span class="dl">'</span><span class="p">),</span>
<span class="na">transport</span><span class="p">:</span> <span class="p">{</span>
<span class="na">target_1</span><span class="p">:</span> <span class="p">{</span>
<span class="na">files</span><span class="p">:</span> <span class="p">[{</span>
<span class="na">expand</span><span class="p">:</span><span class="kc">true</span><span class="p">,</span>
<span class="na">cwd</span><span class="p">:</span> <span class="dl">'</span><span class="s1">sea_modules</span><span class="dl">'</span><span class="p">,</span>
<span class="na">src</span><span class="p">:</span> <span class="dl">'</span><span class="s1">*.js</span><span class="dl">'</span><span class="p">,</span>
<span class="na">dest</span><span class="p">:</span> <span class="dl">'</span><span class="s1">dist</span><span class="dl">'</span>
<span class="p">}]</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">concat</span><span class="p">:</span> <span class="p">{</span>
<span class="na">target_1</span><span class="p">:</span> <span class="p">{</span>
<span class="na">options</span><span class="p">:</span> <span class="p">{</span>
<span class="na">noncmd</span><span class="p">:</span> <span class="kc">true</span>
<span class="p">},</span>
<span class="na">files</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">dist/main.js</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">dist/main.js</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">dist/test.js</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">dist/a.js</span><span class="dl">'</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">uglify</span><span class="p">:</span> <span class="p">{</span>
<span class="na">target_1</span><span class="p">:</span> <span class="p">{</span>
<span class="na">files</span><span class="p">:</span> <span class="p">{</span>
<span class="dl">'</span><span class="s1">dist/main.js</span><span class="dl">'</span><span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">dist/main.js</span><span class="dl">'</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">copy</span> <span class="p">:</span> <span class="p">{</span>
<span class="na">target_1</span> <span class="p">:</span> <span class="p">{</span>
<span class="na">files</span><span class="p">:[</span>
<span class="p">{</span><span class="na">expand</span><span class="p">:</span> <span class="kc">true</span><span class="p">,</span> <span class="na">cwd</span><span class="p">:</span><span class="dl">'</span><span class="s1">dist</span><span class="dl">'</span><span class="p">,</span><span class="na">src</span><span class="p">:</span><span class="dl">'</span><span class="s1">main.js</span><span class="dl">'</span><span class="p">,</span> <span class="na">dest</span><span class="p">:</span><span class="dl">'</span><span class="s1">.</span><span class="dl">'</span><span class="p">,</span> <span class="na">filter</span><span class="p">:</span> <span class="dl">'</span><span class="s1">isFile</span><span class="dl">'</span><span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="p">},</span>
<span class="na">clean</span><span class="p">:</span> <span class="p">{</span>
<span class="na">build</span><span class="p">:</span> <span class="p">{</span>
<span class="na">src</span><span class="p">:</span> <span class="p">[</span><span class="dl">"</span><span class="s2">dist</span><span class="dl">"</span><span class="p">]</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">});</span>
<span class="c1">// 加载包含 "uglify" 任务的插件。 </span>
<span class="nx">grunt</span><span class="p">.</span><span class="nx">loadNpmTasks</span><span class="p">(</span><span class="dl">'</span><span class="s1">grunt-cmd-transport</span><span class="dl">'</span><span class="p">);</span><span class="c1">//提取js模块的id和依赖 </span>
<span class="nx">grunt</span><span class="p">.</span><span class="nx">loadNpmTasks</span><span class="p">(</span><span class="dl">'</span><span class="s1">grunt-cmd-concat</span><span class="dl">'</span><span class="p">);</span><span class="c1">//合并js模块 </span>
<span class="nx">grunt</span><span class="p">.</span><span class="nx">loadNpmTasks</span><span class="p">(</span><span class="dl">'</span><span class="s1">grunt-contrib-uglify</span><span class="dl">'</span><span class="p">);</span><span class="c1">//压缩js模块 </span>
<span class="nx">grunt</span><span class="p">.</span><span class="nx">loadNpmTasks</span><span class="p">(</span><span class="dl">'</span><span class="s1">grunt-mcopy</span><span class="dl">'</span><span class="p">);</span><span class="c1">//复制文件 </span>
<span class="nx">grunt</span><span class="p">.</span><span class="nx">loadNpmTasks</span><span class="p">(</span><span class="dl">'</span><span class="s1">grunt-contrib-clean</span><span class="dl">'</span><span class="p">);</span><span class="c1">//清空文件夹 </span>
<span class="c1">// 默认被执行的任务列表。 </span>
<span class="nx">grunt</span><span class="p">.</span><span class="nx">registerTask</span><span class="p">(</span><span class="dl">'</span><span class="s1">default</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">transport</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">concat</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">uglify</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">copy</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">clean</span><span class="dl">'</span><span class="p">]);</span>
<span class="p">};</span>
</code></pre></div></div>
<p>6.打开命令行,进入nodejs目录,运行grunt命令
<img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gruntjs结合seajs开发-3.jpg" alt="" /></p>
<p>此时将会在nodejs目录下生成合并后的main.js,该文件即我们最终需要的文件</p>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="dl">"</span><span class="s2">main</span><span class="dl">"</span><span class="p">,[</span><span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">],</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">c</span><span class="p">){</span><span class="nx">a</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">),</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">)}),</span><span class="nx">define</span><span class="p">(</span><span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">,[</span><span class="dl">"</span><span class="s2">a</span><span class="dl">"</span><span class="p">],</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">c</span><span class="p">){</span><span class="nx">a</span><span class="p">(</span><span class="dl">"</span><span class="s2">a.js</span><span class="dl">"</span><span class="p">),</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行test.js</span><span class="dl">"</span><span class="p">)}),</span><span class="nx">define</span><span class="p">(</span><span class="dl">"</span><span class="s2">a</span><span class="dl">"</span><span class="p">,[],</span><span class="kd">function</span><span class="p">(</span><span class="nx">a</span><span class="p">,</span><span class="nx">b</span><span class="p">,</span><span class="nx">c</span><span class="p">){</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行a.js</span><span class="dl">"</span><span class="p">)});</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gruntjs结合seajs开发-4.jpg" alt="" /></p>
<p>如果只运行transport任务:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">grunt</span><span class="p">.</span><span class="nx">registerTask</span><span class="p">(</span><span class="dl">'</span><span class="s1">default</span><span class="dl">'</span><span class="p">,</span> <span class="p">[</span><span class="dl">'</span><span class="s1">transport</span><span class="dl">'</span><span class="cm">/*,'concat','uglify','copy','clean'*/</span><span class="p">]);</span>
</code></pre></div></div>
<p>则将只提取js模块的id和依赖
<img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gruntjs结合seajs开发-5.jpg" alt="" /></p>
<p>提取后的文件:</p>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="dl">"</span><span class="s2">main</span><span class="dl">"</span><span class="p">,</span> <span class="p">[</span> <span class="dl">"</span><span class="s2">test</span><span class="dl">"</span> <span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span> <span class="nx">exports</span><span class="p">,</span> <span class="nx">module</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>test.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="dl">"</span><span class="s2">test</span><span class="dl">"</span><span class="p">,</span> <span class="p">[</span> <span class="dl">"</span><span class="s2">a</span><span class="dl">"</span> <span class="p">],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span> <span class="nx">exports</span><span class="p">,</span> <span class="nx">module</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">a.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>a.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="dl">"</span><span class="s2">a</span><span class="dl">"</span><span class="p">,</span> <span class="p">[],</span> <span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span> <span class="nx">exports</span><span class="p">,</span> <span class="nx">module</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行a.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>7.运行sea.html进行测试,结果如下:
<img src="https://wanls4583.github.io/images/posts/构建工具/2017-06-30-gruntjs结合seajs开发-6.jpg" alt="" /></p>
<p>可以看到,成功合并了文件。</p>
前端性能优化之-js异步加载
2017-06-30T03:52:00+00:00
https://blog.lisong.hn.cn/%E5%89%8D%E7%AB%AF%E4%BC%98%E5%8C%96/2017/06/30/前端性能优化之-js异步加载
<blockquote>
<p>默认情况JavaScript是同步加载的,也就是javascript的加载是阻塞的,后面的元素要等待javascript加载完毕后才能进行再加载,对于一些意义不是很大的javascript,如果放在页头会导致加载很慢的话,是会严重影响用户体验的。</p>
</blockquote>
<p>因此有时候有必要实现js的异步加载,js异步主要有三种方式:defer(内联模式下仅IE可用),async(HTML5新属性),用js创建script,接下来,我们就来一起来看看这三种方式的使用。</p>
<h2 id="defer">defer</h2>
<p><em>defer的官方定义:</em></p>
<p>defer 属性规定是否对脚本执行进行延迟,直到页面加载为止。如果您的脚本不会改变文档的内容,可将 defer 属性加入到 <script> 标签中,以便加快处理文档的速度。因为浏览器知道它将能够安全地读取文档的剩余部分而不用执行脚本,它将推迟对脚本的解释,直到文档已经显示给用户为止。</p>
<p>示例:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
window.onload=function(){
console.log("页面加载完成");
}
document.addEventListener('DOMContentLoaded',function(){
console.log("文档元素加载完成");
},false);
</script>
<script type="text/javascript" defer="defer">
console.log("有defer属性的脚本内容");
console.log(document.getElementById("p1").innerHTML);
</script>
<script type="text/javascript">
console.log("没有defer属性的脚本内容");
</script>
</head>
<body>
<p id="p1">测试内容</p>
</body>
</html>
</code></pre></div></div>
<p>IE8下的测试结果:*
<img src="https://wanls4583.github.io/images/posts/前端优化/2017-06-30-js异步加载-1.jpg" alt="" /></p>
<p>通过输出的日志可以看到,文档会先解析页面,等页面解析完成后才去执行defer属性标记的脚步内容,最后再触发window的onload(页面的文档结构和图片都加载完成后触发)事件,注意:IE8不支持DOMContentLoad(页面文档结构解析完成)事件。</p>
<p>360浏览器测试结果:
<img src="https://wanls4583.github.io/images/posts/前端优化/2017-06-30-js异步加载-2.jpg" alt="" /></p>
<p>可以看到,360浏览器并不支持defer属性,注意:DOMContentLoad事件先于onload事件。</p>
<p>不过对于外部js文件,defer在各浏览器上都是支持的</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" defer="defer" src="test.js">
</script>
<script type="text/javascript">
console.log(2)
</script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p>test.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">out:1</span><span class="dl">'</span><span class="p">);</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/前端优化/2017-06-30-js异步加载-3.png" alt="" /></p>
<h2 id="async">async</h2>
<p><em>async官方解释:</em></p>
<p>async 属性规定一旦脚本可用,则会异步执行。</p>
<p>注释:async 属性仅适用于外部脚本(只有在使用 src 属性时)。</p>
<p>注释:有多种执行外部脚本的方法:</p>
<ul>
<li>如果 async=”async”:脚本相对于页面的其余部分异步地执行(当页面继续进行解析时,脚本将被执行,也就是脚本的下载和页面的解析异步执行,脚本一下载完就立即执行)</li>
<li>如果不使用 async 且 defer=”defer”:脚本将在页面完成解析时执行</li>
<li>如果既不使用 async 也不使用 defer:在浏览器继续解析页面之前,立即读取并执行脚本</li>
</ul>
<p>示例:</p>
<p>async.html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
window.onload=function(){
console.log("页面加载完成");
}
document.addEventListener('DOMContentLoaded',function(){
console.log("文档元素加载完成");
},false);
</script>
<script type="text/javascript" src="test.js" async="async">
</script>
</head>
<body>
<script type="text/javascript">
console.log("没有async属性的脚本内容");
setTimeout(function(){
var p = document.createElement("p");
p.innerHTML = "动态创建的内容";
document.body.appendChild(p);
},600)
</script>
</body>
</html>
</code></pre></div></div>
<p>test.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">有async属性的脚本内容</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="dl">"</span><span class="s2">p</span><span class="dl">"</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">innerHTML</span><span class="p">);</span>
</code></pre></div></div>
<p>tomcat下用360浏览器测试结果:
<img src="https://wanls4583.github.io/images/posts/前端优化/2017-06-30-js异步加载-4.jpg" alt="" /></p>
<p>注意图中红线框中的内容,设置网络延迟500ms以便测试,此时test.js的下载和运行耗时总共为676,因为我们在用js动态创建p标签时设置了延时为600ms,当test.js执行时,p标签已经动态生成了,所以可以获取到p标签,但是当我们用js动态创建p标签设置延时为700ms(大于test.js的下载和运行耗时)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><body>
<script type="text/javascript">
console.log("没有async属性的脚本内容");
setTimeout(function(){
var p = document.createElement("p");
p.innerHTML = "动态创建的内容";
document.body.appendChild(p);
},700)
</script>
</body>
</code></pre></div></div>
<p>其结果如下:
<img src="https://wanls4583.github.io/images/posts/前端优化/2017-06-30-js异步加载-5.jpg" alt="" /></p>
<p>此时,test.js运行时是获取不到动态生成的p标签的,因为其下载和运行耗时为663ms,小于我们设置的延时700ms。async属性标记的外部脚本在DOMContentLoaded事件之后onLoad事件之前执行。</p>
<p>以下是一张图(引用自https://segmentfault.com/q/1010000000640869)
<img src="https://wanls4583.github.io/images/posts/前端优化/2017-06-30-js异步加载-6.jpg" alt="" /></p>
<p>蓝色线代表网络读取,红色线代表执行时间,这俩都是针对脚本的;绿色线代表 HTML 解析。</p>
<p>此图告诉我们以下几个要点:</p>
<ul>
<li>defer 和 async 在网络读取(下载)这块儿是一样的,都是异步的(相较于 HTML 解析)</li>
<li>它俩的差别在于脚本下载完之后何时执行,显然 defer 是最接近我们对于应用脚本加载和执行的要求的</li>
<li>关于 defer,此图未尽之处在于它是按照加载顺序执行脚本的,这一点要善加利用</li>
<li>async 则是一个乱序执行的主,反正对它来说脚本的加载和执行是紧紧挨着的,所以不管你声明的顺序如何,只要它加载完了就会立刻执行</li>
</ul>
<p>仔细想想,async 对于应用脚本的用处不大,因为它完全不考虑依赖(哪怕是最低级的顺序执行),不过它对于那些可以不依赖任何脚本或不被任何脚本依赖的脚本来说却是非常合适的,最典型的例子:Google Analytics</p>
<h2 id="动态创建script标签">动态创建script标签</h2>
<p>示例:</p>
<p>async.html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
window.onload=function(){
console.log("页面加载完成");
}
document.addEventListener('DOMContentLoaded',function(){
console.log("文档元素加载完成");
},false);
</script>
<script type="text/javascript">
function loadScript(url, callback){
var script = document.createElement("script");
script.type = "text/javascript";
if (script.readyState){ //IE
script.onreadystatechange = function(){
if (script.readyState == "loaded" || script.readyState == "complete"){
script.onreadystatechange = null;
callback();
}
};
} else { //Others: Firefox, Safari, Chrome, and Opera
script.onload = function(){
callback();
};
}
script.src = url;
document.getElementsByTagName("head")[0].appendChild(script);
}
loadScript("test.js",function(){});
</script>
</head>
<body>
<script type="text/javascript">
setTimeout(function(){
var p = document.createElement("p");
p.innerHTML = "动态创建的内容";
document.body.appendChild(p);
},600);
</script>
</body>
</html>
</code></pre></div></div>
<p>test.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">js加载的脚本内容</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="dl">"</span><span class="s2">p</span><span class="dl">"</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">innerHTML</span><span class="p">);</span>
</code></pre></div></div>
<p>360浏览器测试结果:
<img src="https://wanls4583.github.io/images/posts/前端优化/2017-06-30-js异步加载-7.jpg" alt="" /></p>
<p>把延迟改成700ms:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><body>
<script type="text/javascript">
setTimeout(function(){
var p = document.createElement("p");
p.innerHTML = "动态创建的内容";
document.body.appendChild(p);
},700);
</script>
</body>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/前端优化/2017-06-30-js异步加载-8.jpg" alt="" /></p>
<p>通过这个例子可以看出,用js动态创建script的方式来加载js脚本,其效果和async属性是一样的。</p>
详解vertical-algin
2017-06-29T11:59:03+00:00
https://blog.lisong.hn.cn/css/2017/06/29/详解vertical-algin
<p>首先我们来看下官方给出的<code class="language-plaintext highlighter-rouge">line-height</code>属性的解释:</p>
<p><code class="language-plaintext highlighter-rouge">line-height</code>属性会影响行框的布局。在应用到一个块级元素时,它定义了该元素中基线之间的最小距离而不是最大距离。<code class="language-plaintext highlighter-rouge">line-height</code> 与 <code class="language-plaintext highlighter-rouge">font-size</code> 的计算值之差(在 CSS 中成为“行间距”)分为两半,分别加到一个文本行内容的顶部和底部。可以包含这些内容的最小框就是行框。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body</span> <span class="na">style=</span><span class="s">"margin: 0"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background: black;line-height: 100px;"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: red;font-size: 40px"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>根据官方的解释,div的的高度应该为100px,然而在浏览器debug模式下的高度确实108px,而且上下的半行距并不一样</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-1.png" alt="" /></p>
<p>这到底是为什么呢?这个问题曾困扰我很长时间,最后查了多方资料,才知道原来在HTML5文档声明下,块状元素内部的内联元素的行为表现,就好像块状元素内部还有一个(更有可能两个-前后)看不见摸不着没有宽度没有实体的空白节点,这个假想又似乎存在的空白节点,我们可以称之为“幽灵空白节点”。这个幽灵空白节点有默认的字体大小和行高,所以上面的例子其实是这样的:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-2.jpg" alt="" /></p>
<p>左边框为span行内框(行内框即内联元素形成的框,包括了内联元素因为line-height形成的上下间距),右边框为幽灵空白节点的行内框,它们两的高度都是100px(父元素指定了<code class="language-plaintext highlighter-rouge">line-height:100px</code>),因为一行内的所有内联元素都要相对父元素的基线(本行内行高最大的第一个内联元素的基线)对齐,而空白幽灵节点的默认字体小于40px,因此空白幽灵节点行内框向下移动了一点。</p>
<p>如果我们同时指定父元素字体的大小:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body</span> <span class="na">style=</span><span class="s">"margin: 0"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background: black;line-height: 100px;font-size:40px"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: red;font-size:40px"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>此时结果和我们预期的一样了:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-3.jpg" alt="" /></p>
<p>我们可以看到此时div的高度和指定的行高是一样的,之所以会这样,是因为我们给父元素加上<code class="language-plaintext highlighter-rouge">font-size</code>的时候就给幽灵空白节点指定了字体大小,只要让其字体大小和以及行高都和内联元素(该例中也就是span元素)一样,那么它们的行内框的顶部以及基线都会在同一条水平线上,也就不会上移或者下移了。(ps:家里好冷,我的双手已经快僵了)</p>
<p>好了,发了下牢骚,现在我们来浓重介绍下<code class="language-plaintext highlighter-rouge">line-height</code>的好基友,也就是<code class="language-plaintext highlighter-rouge">vertical-align</code>,之所以叫它们是好基友,是因为<code class="language-plaintext highlighter-rouge">vertical</code>的表现基本依赖于<code class="language-plaintext highlighter-rouge">line-height</code>。</p>
<p>同样,我们先来看一下官方给出的<code class="language-plaintext highlighter-rouge">vertial-algin</code>的解释:<code class="language-plaintext highlighter-rouge">vertial-algin</code>属性定义行内元素的基线相对于该元素所在行的基线的垂直对齐。允许指定负长度值和百分比值,这会使元素降低而不是升高。在表单元格中,这个属性会设置单元格框中的单元格内容的对齐方式。</p>
<table class="dataintable " style="color: rgb(51, 51, 51); font-family: Arial; font-size: 14px; background-color: rgb(255, 255, 255); margin: 10px 0px 0px; padding: 0px; border: 1px solid rgb(170, 170, 170); border-collapse: collapse; width: 709px;">
<tbody style="margin: 0px; padding: 0px; border: 0px;">
<tr style="margin: 0px; padding: 0px; border: 0px;">
<th style="margin: 0px; padding: 5px 15px 5px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: baseline; background-color: rgb(213, 213, 213);">
值
</th>
<th style="margin: 0px; padding: 5px 15px 5px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: baseline; background-color: rgb(213, 213, 213);">
描述
</th>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
baseline
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
默认。元素放置在父元素的基线上。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
sub
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
垂直对齐文本的下标。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
super
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
垂直对齐文本的上标
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
top
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
把元素的顶端与行中最高元素的顶端对齐
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
text-top
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
把元素的顶端与父元素字体的顶端对齐
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
middle
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
把此元素放置在父元素的中部。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
bottom
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
把元素的顶端与行中最低的元素的顶端对齐。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
text-bottom
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
把元素的底端与父元素字体的底端对齐。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
length
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
%
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
使用 "line-height" 属性的百分比值来排列此元素。允许使用负值。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
inherit
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top; background-color: rgb(239, 239, 239);">
规定应该从父元素继承 vertical-align 属性的值。
</td>
</tr>
</tbody>
</table>
<p>根据官方的解释我们来看一个例子:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body</span> <span class="na">style=</span><span class="s">"margin: 0"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background: black;"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: red;font-size:60px;line-height: 60px"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: #fff;font-size:20px;line-height: 60px;vertical-align: bottom"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>大多数情况下,我们期待的是两个English的底部应该对其,然而结果确实这样的:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-4.png" alt="" /></p>
<p>两个 English 的底部并没有对其,但细心的同学可能会发现,两个内联元素是上下垂直对齐的,为什么会产生这种情况呢,我们的代码明明是指定<code class="language-plaintext highlighter-rouge">vertical-align:bottom</code>,别急,我们慢慢来分析。</p>
<p>首先,它们的行高是一样的,都是60px,咦,好像有点感觉了,给内联元素添加<code class="language-plaintext highlighter-rouge">vertical-align</code>样式,其基准是不是以该元素的行高(也即该元素的行内框)来算呢,没错,你猜对了,给第二个内联元素添加<code class="language-plaintext highlighter-rouge">vertical-align:bottom</code>后,它们的行内框的底部在同一条水平线上,因为他们的行高都是60px,此时他们的顶部也在同一条水平线上,因为第二个元素的上下间距是一样的,此时就产生了两个元素上下垂直居中的效果,虽然我们指定的<code class="language-plaintext highlighter-rouge">vertical-align:bottom</code>。</p>
<p>如果代码是这样:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body</span> <span class="na">style=</span><span class="s">"margin: 0"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background: black;"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: red;font-size:60px;line-height: 60px"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: #fff;font-size:20px;line-height: 20px;vertical-align: bottom"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>结果就和我们预期的一样了:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-5.png" alt="" /></p>
<p>这里因为第二个元素的行高为20px,和其字体的大小一样,所以其字体内容的底部刚好就是其行内框的底部,也就得到了我们想要的结果了。</p>
<p>好了,解决了这个问题,我们再来看一个例子:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body</span> <span class="na">style=</span><span class="s">"margin: 0"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background: black;"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: red;font-size:60px;line-height: 100px"</span><span class="nt">></span>English我<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: #fff;font-size:20px;line-height: 20px;vertical-align: text-bottom"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>按照官方表面的解释,我们期待的应该是蓝色 English 行内框的底部应该和红色红内框内容的底部对齐,然而结果是这样的:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-6.png" alt="" /></p>
<p>我们可以明显的看到蓝色English并没有和红色 English 的内容的底部对齐,读到这里,可能很多同学都在想,就一个属性,咋就这么多坑呢,呵呵,其实不是坑多,而是我们没有仔细的理解css官方的释义:</p>
<table class="dataintable " style="border-style: solid; border-color: rgb(170, 170, 170); margin: 10px 0px 0px; padding: 0px; border-collapse: collapse; width: 709px; font-family: Verdana, Arial, 宋体; background-color: rgb(249, 249, 249);">
<tbody style="margin: 0px; padding: 0px; border: 0px;">
<tr style="margin: 0px; padding: 0px; border: 0px;">
<td style="border-style: solid; border-color: rgb(170, 170, 170); margin: 0px; padding: 6px 15px 6px 6px; vertical-align: text-top; background-color: rgb(239, 239, 239);">
text-bottom
</td>
<td style="border-style: solid; border-color: rgb(170, 170, 170); margin: 0px; padding: 6px 15px 6px 6px; vertical-align: text-top; background-color: rgb(239, 239, 239);">
把元素的底端与父元素字体的底端对齐。<br />
</td>
</tr>
</tbody>
</table>
<p>注意这句话:父元素字体的底端。这里其实有个陷阱,它这里的对齐是根据父元素内的幽灵空白节点的底端来对齐的,在不给父元素设置字体大小和行高的情况下,幽灵空白节点有个默认的字体大小和行高,这个默认的值和红色English的行高和字体大小是不一样,这也就导致了和我们预期的结果不一样的效果。</p>
<p>如果我们给父元素加上行高和字体大小:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body</span> <span class="na">style=</span><span class="s">"margin: 0"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background: black;font-size:60px;line-height: 100px"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: red;font-size:60px;line-height: 100px"</span><span class="nt">></span>English我<span class="nt"></span></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: #fff;font-size:20px;line-height: 20px;vertical-align: text-bottom"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-7.png" alt="" /></p>
<p>此时的结果就和我们预期的一样了,之所以会这样,是因为幽灵空白节点的行高和字体大小与红色English的行高和字体大小一模一样。</p>
<p>属性值<code class="language-plaintext highlighter-rouge">top</code>和<code class="language-plaintext highlighter-rouge">text-top</code>,它们刚好和<code class="language-plaintext highlighter-rouge">bottom</code>以及<code class="language-plaintext highlighter-rouge">text-bottom</code>相反,我就不赘述了,关于属性值<code class="language-plaintext highlighter-rouge">middle、sub、supper</code>,我们下次再说,不知不觉以及零点了,该睡觉了,真累</p>
<p>接着上次的来说,我们再来看一个例子:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body</span> <span class="na">style=</span><span class="s">"margin: 0"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background: black;font-size:60px;line-height: 100px"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: red;"</span><span class="nt">></span>Englishx<span class="nt"></span><span</span> <span class="na">style=</span><span class="s">"background: #fff;font-size:20px;line-height: 20px;vertical-align: middle"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-8.png" alt="" /></p>
<p>按照官方的解释,我们可以直观的理解为蓝色 English 应该和红色 English 上下垂直对齐,但其实并没有达到我们想要的结果,因为给内联元素设置<code class="language-plaintext highlighter-rouge">vertical-align:middle</code>样式,那么其中心位置将相对于父元素基线上x的中线对齐,该x字体的大小为父元素设置的字体大小,以下例子很好的证实了这一点。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body style="margin: 0">
<div style="background: black;font-size:60px;line-height: 100px">
<span style="background: red;font-size:80px;">Englishx</span><span style="background: #fff;font-size:20px;line-height: 20px;vertical-align: middle">English</span><span style="background: red;">xEnglish</span>
</div>
</body>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-9.png" alt="" /></p>
<p>在该例中,左边红色部分的字体为80px,右边红色部分的字体为父元素的字体大小,我们给蓝色部分设置<code class="language-plaintext highlighter-rouge">vertical-align:middle</code>,可以明显看到其中心是相对于右边红色部分的x字母的中心对其的,这也很好的说明了前面的一点(给内联元素设置<code class="language-plaintext highlighter-rouge">vertical-align:middle</code>样式,那么其中心位置将相对于父元素基线上x的中线对齐,该x字体的大小为父元素设置的字体大小)</p>
<p>关于<code class="language-plaintext highlighter-rouge">vertical-align:supper</code>和<code class="language-plaintext highlighter-rouge">vertical-align:sub</code>,没什么好说的,直接看例子吧:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body</span> <span class="na">style=</span><span class="s">"margin: 0"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">"background: black;font-size:60px;line-height: 100px"</span><span class="nt">></span>
<span class="nt"><span</span> <span class="na">style=</span><span class="s">"background: red;"</span><span class="nt">></span>English<span class="nt"></span><sup</span> <span class="na">style=</span><span class="s">"background: red;"</span><span class="nt">></span>Englishx<span class="nt"></sup><span</span> <span class="na">style=</span><span class="s">"background: #fff;font-size:20px;line-height: 20px;vertical-align: super"</span><span class="nt">></span>English<span class="nt"></span></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-06-29-详解line-height与vertical-algin-10.png" alt="" /></p>
<p>我们可以看到,给内联元素加上<code class="language-plaintext highlighter-rouge">vertical-align:super</code>样式后,其基线会与该行内上标元素的基线对齐。需要注意的是该行内所有的上标元素的基线都在一条水平线上,就像所有的行内元素都在一条基线上一样;<code class="language-plaintext highlighter-rouge">vertical-align:sub</code>原理和<code class="language-plaintext highlighter-rouge">vertical-align:super</code>一样,它与<code class="language-plaintext highlighter-rouge">super</code>正好相反,其基线会与该行内下标标元素的基线对齐。
好了,到这里基本上算是把<code class="language-plaintext highlighter-rouge">line-height</code>和<code class="language-plaintext highlighter-rouge">vertical-align</code>讲完了,有疑问的地方可以联系作者,谢谢</p>
IE css3常用属性兼容性
2017-06-29T08:22:41+00:00
https://blog.lisong.hn.cn/css/2017/06/29/IE css3常用属性兼容性
<p>IE css3常用属性兼容性:</p>
<ul>
<li>min-width,min-height,max-width,max-height:ie7+</li>
<li>vw, vh, vmin:ie9+(ie不支持vmax)</li>
<li>box-sizing:ie8+</li>
<li>@media:ie9+</li>
<li>rem:ie9+</li>
</ul>
<p>vw:相对于视口的宽度。视口被均分为100单位的vw</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">h1</span> <span class="p">{</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">8vw</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>vh:相对于视口的高度。视口被均分为100单位的vh</p>
<p>vmax:相对于视口的宽度或高度中较大的那个。其中最大的那个被均分为100单位的vmax</p>
<p>vmin:相对于视口的宽度或高度中较小的那个。其中最小的那个被均分为100单位的vmin</p>
requirejs与seajs的比较
2017-06-29T06:46:21+00:00
https://blog.lisong.hn.cn/%E6%A8%A1%E5%9D%97%E5%8C%96/2017/06/29/requirejs与seajs的比较
<p>相信大家都知道seaJs与requireJs这两个框架的作用,它们都是用来帮助前端程序员进行模块化开发的的框架,在讲seaJs与requireJs之前,我们先来说一下为什么我们的项目需要模块化。</p>
<p>如果项目比较小,我们是不需要用到模块化的,但是一旦项目大起来,你会发现代码越来越难以进行维护,这些问题主要包括命名冲突和js依赖问题,下面举例来说明这些问题。</p>
<p><em>(1)命名冲突</em></p>
<p>A程序员开发的代码:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="B.js"></script>
<script type="text/javascript">
function tab(){};
</script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p>B程序员开发的代码:B.js</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">tab</span><span class="p">(){};</span>
</code></pre></div></div>
<p>本来A程序员是想引用B程序员所开发的功能tab(),结果因为自己不重命名了tab(),导致引入的功能不能用了,这就是命名冲突</p>
<p><em>(2)js依赖问题</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="B.js"></script>
<script type="text/javascript" src="C.js"></script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p>其中C.js依赖B.js的功能,要使用C.js,js必须先加载B.js,假如我们以及开发了很多页面,这些页面中都使用了C.js,突然有一天,来了新需求,C.js升级了功能,不在需要B.js里的功能,这时我们就需要把每个页面中的B.js移除掉,这种工作效率是及其低效的。</p>
<p>好了,出现了问题,自然就会有解决的方法出现,seaJs和requireJs框架主要就是用来解决这两个问题的。</p>
<h3 id="seajs示例1">seaJs示例1</h3>
<p>sea1.html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="sea-debug.js"></script>
<script type="text/javascript">
seajs.use("main.js",function(){
console.log("执行入口模块回调函数");
})
</script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/模块化/2017-06-29-requirejs与seajs的比较-1.jpg" alt="" /></p>
<h3 id="requirejs示例1">requireJs示例1</h3>
<p>req1.html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="require2.1.11.js" data-main="main"></script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/模块化/2017-06-29-requirejs与seajs的比较-2.jpg" alt="" /></p>
<font style="background:#eee">总结1:seaJs加载入口模块是通过sea.use()函数来加载的,requireJs是通过data-main属性来加载的</font>
<h3 id="seajs示例2">seaJs示例2</h3>
<p>sea2.html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="sea-debug.js"></script>
<script type="text/javascript">
seajs.use("main.js",function(){
console.log("执行入口模块回调函数");
})
</script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span><span class="c1">//require参数固定,seaJs会扫描回调函数的require字符串,预加载模块</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">);</span><span class="c1">//同步执行</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">main.js执行结束</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>test.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">})</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/模块化/2017-06-29-requirejs与seajs的比较-3.jpg" alt="" /></p>
<p>如果定义模块时一定要把require参数改变,则需要使用异步加载require.async():</p>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require1</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="c1">//require1("test.js");//不会加载</span>
<span class="nx">require1</span><span class="p">.</span><span class="k">async</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span><span class="c1">//异步加载模块</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js回调函数</span><span class="dl">"</span><span class="p">);</span>
<span class="p">})</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">main.js执行结束</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/模块化/2017-06-29-requirejs与seajs的比较-4.jpg" alt="" /></p>
<p>此时,require加载为异步的,test.js在main.js执行完之后才执行。</p>
<p>如果定义模块时声明了依赖,如:
main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="dl">""</span><span class="p">,[</span><span class="dl">"</span><span class="s2">a.js</span><span class="dl">"</span><span class="p">],</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span><span class="c1">//不会再扫描require字符串进行预加载</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">a.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">);</span><span class="c1">//不加载</span>
<span class="p">});</span>
</code></pre></div></div>
<p>a.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行a.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">})</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/模块化/2017-06-29-requirejs与seajs的比较-5.jpg" alt="" /></p>
<p>此时,不会在扫描回调函数中的require字符串来加载模块</p>
<h3 id="requirejs示例2">requireJs示例2</h3>
<p>req2.html:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript" src="require2.1.11.js" data-main="main"></script>
</head>
<body>
</body>
</html>
</code></pre></div></div>
<p>main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span><span class="c1">//原理和seaJs一样,也是扫描require字符串加载模块,只不过在加载完后会立即执行该模块的回调函数</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">);</span><span class="c1">//同步执行</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">main.js执行完成</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>a.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">})</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/模块化/2017-06-29-requirejs与seajs的比较-6.jpg" alt="" /></p>
<p>如果定义模块时一定要把require参数改变,则需要使用异步加载require([],function(){}):</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="kd">function</span><span class="p">(</span><span class="nx">require1</span><span class="p">,</span><span class="nx">exports</span><span class="p">,</span><span class="nx">module</span><span class="p">){</span><span class="c1">//不会再扫描require字符串进行预加载</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="c1">//require1("test.js");//会报错</span>
<span class="nx">require1</span><span class="p">([</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">],</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">加载完test.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">main.js执行完成</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/模块化/2017-06-29-requirejs与seajs的比较-7.jpg" alt="" /></p>
<p>如果定义模块时声明了函数依赖,如:
main.js:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">define</span><span class="p">(</span><span class="dl">""</span><span class="p">,[</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">],</span><span class="kd">function</span><span class="p">(</span><span class="nx">test</span><span class="p">){</span><span class="c1">//不会再扫描require字符串进行预加载</span>
<span class="nx">require</span><span class="p">(</span><span class="dl">"</span><span class="s2">test.js</span><span class="dl">"</span><span class="p">);</span><span class="c1">//重复加载将忽略</span>
<span class="c1">//require("a.js");//报错</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">执行main.js</span><span class="dl">"</span><span class="p">);</span>
<span class="p">});</span>
</code></pre></div></div>
<p>测试结果:
<img src="https://wanls4583.github.io/images/posts/模块化/2017-06-29-requirejs与seajs的比较-8.jpg" alt="" /></p>
<p>此时不可以在回调函数里用require再加载未声明的模块,因为没有进行require字符串扫描进行预加载</p>
<font style="background:#eee">总结2:seaJs和requireJs对模块的加载原理基本一样,只是seaJs遵循CMD规范,加载完模块后并不会立即执行,而是等待执行require函数时候才执行模块的回调函数,而requireJs遵循AMD规范,加载完模块后会立即执行模块的回调函数。</font>
javascript笔记--(第二十三章)JSON
2017-06-28T10:06:09+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第二十三章)JSON
<h2 id="json">JSON</h2>
<p>JSON和XML类型,都是一种结构化的数据表示方式。所以,JSON并不是JavaScript独有的数据格式,其他很多语言都可以对JSON进行解析和序列化。</p>
<h2 id="json语法">JSON语法</h2>
<p>JSON的语法可以表示三种类型的值:简单值,对象,数组。</p>
<h3 id="简单值">简单值</h3>
<p>可以在JSON中表示字符串、数值、布尔值和null。但JSON不支持JavaScript中的特殊值undefined。</p>
<h3 id="对象">对象</h3>
<p>JSON中的对象表示法需要加上双引号</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
{
"name" : "Lee",//使用双引号,否则转换会出错
"age" : 100
}
</script>
</code></pre></div></div>
<h3 id="数组">数组</h3>
<p>[100, “Lee”, true]</p>
<p>一般比较常用的一种复杂形式是数组结合对象的形式:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
[
{
"title" : "a",
"num" : 1
},
{
"title" : "b",
"num" : 2
},
{
"title" : "c",
"num" : 3
}
]
</script>
</code></pre></div></div>
<h3 id="解析和序列化">解析和序列化</h3>
<p>JSON对象提供了两个方法,一个是将原生JavaScript值转换为JSON字符串:stringify();另一个是将JSON字符串转换为JavaScript原生值:parse()。</p>
<p><em>stringify()</em></p>
<p>stringify()方法接受三个参数,第一个是必须的,其他两个可选。第二个参数可以是一个数组,也可以是一个函数,用于过滤结果。第三个个参数则表示是否在JSON字符串中保留缩进。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = [{name : 'a', age : 1, height : 177},{name : 'b', age : 2, height : 188}];
var json = JSON.stringify(box, ['name'],0);//[{"name":"a"},{"name":"b"}]
console.log(json);
</script>
</code></pre></div></div>
<p>如果不需要保留缩进,则不填即可;如果不需要过滤结果,但又要保留缩进,则讲过滤结果的参数设置为null。如果采用函数,可以进行复杂的过滤</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = [{name : 'a', age : 1, height : 177},{name : 'b', age : 2, height : 188}];
var json = JSON.stringify(box, ['name'],4);
console.log(json);
</script>
</code></pre></div></div>
<p>运行结果
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第二十三章)JSON-1.jpg" alt="" /></p>
<p>函数不能删除键值对,只能修改,并且不能返回null或者空字符串</p>
<p>还有一种方法可以自定义过滤一些数据,使用toJSON()方法,可以将某一组对象里指定返回某个值。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = [{name : 'a', age : 1, height : 177, toJSON : function () {
return this.name;
}},{name : 'b',age : 2, height : 188, toJSON : function () {
return this.name;
}}];
var json = JSON.stringify(box, function (key, value) {
switch (key) {
case 'name' :
return 'Mr. ' + value;
case 'age' :
return value + 'year';
default :
return value;
}
}, 4);
console.log(json);
</script>
</code></pre></div></div>
<p>运行结果
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第二十三章)JSON-2.jpg" alt="" /></p>
<p>如果对象里已经有了toJSON函数,则第二个参数是无效的</p>
<p><em>parse()</em></p>
<p>parse()接受两个参数,第一个是必须的,第二个参数是一个函数(数组无效)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = '[{"name" : "a","age" : 1},{"name" : "b","age" : 2}]';
var json = JSON.parse(box, function (key, value) {
if (key == 'name') {
return 'Mr. ' + value;
} else {
return value;
}
});
console.log(json[0].name);
</script>
</code></pre></div></div>
javascript笔记--(第二十二章)事件
2017-06-28T09:57:25+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第二十二章)事件
<h2 id="target和currenttarget的区别">target和currentTarget的区别</h2>
<p>currentTarget始终是监听事件者,而target是事件的真正发出者</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="outdiv" style="width:300px;margin-left:100px;height:300px;background-color: red">
<div id="indiv" style="width:100px;height: 100px;background-color: blue;"></div>
</div>
</body>
<script type="text/javascript">
document.getElementById("outdiv").onclick = function (evt) {
var e = evt || window.event;
console.log(e.currentTarget);
console.log(e.target);
};
</script>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第二十二章)事件-1.jpg" alt="" /></p>
<p>蓝色框表示点击蓝色区域时的输出,红色框表示点击红色区域时的输出。</p>
<h2 id="事件流">事件流</h2>
<p>事件流是描述的从页面接受事件的顺序,当几个都具有事件的元素层叠在一起的时候,那么你点击其中一个元素,并不是只有当前被点击的元素会触发事件,而层叠在你点击范围的所有元素都会触发事件。事件流包括两种模式:冒泡和捕获。</p>
<p>事件冒泡,是从里往外逐个触发。事件捕获,是从外往里逐个触发。那么现代的浏览器默认情况下都是冒泡模型,而捕获模式则是早期的Netscape默认情况。而现在的浏览器要使用DOM2级模型的事件绑定机制才能手动定义事件流模式。</p>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第二十二章)事件-2.jpg" alt="" /></p>
<p>在阻止冒泡的过程中,W3C和IE采用的不同的方法,那么我们必须做一下兼容。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
function stopPro(evt) {
var e = evt || window.event;
window.event ? e.cancelBubble = true : e.stopPropagation();
}
</script>
</code></pre></div></div>
<h2 id="事件绑定">事件绑定</h2>
<h3 id="传统事件绑定的问题">传统事件绑定的问题</h3>
<p>前面定义的事件函数会被后面定义的事件函数覆盖</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
window.onload = function () {//第一组程序项目或第一个JS文件
alert('Lee');
};
window.onload = function () {//第二组程序项目或第二个JS文件,会覆盖上面的函数
alert('Mr.Lee');
};
</script>
</code></pre></div></div>
<p>解决覆盖问题</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
function addEvent(obj, type, fn) {//取代传统事件处理函数
var saved = null;//保存每次触发的事件处理函数
if (typeof obj['on' + type] == 'function') {//判断是不是事件
saved = obj['on' + type];//如果有,保存起来
}
obj['on' + type] = function () {
if (saved) saved();//执行上一个
fn.call(this);//执行函数,把this传递过去
};
}
var box = document.getElementById("outdiv");
addEvent(box,"click",function(){
console.log("fun1");
});
addEvent(box,"click",function(){
console.log("fun2");
});
addEvent(box,"click",function(){
console.log("fun3");
});
</script>
</code></pre></div></div>
<h2 id="w3c事件处理函数">W3C事件处理函数</h2>
<p>“DOM2级事件”定义了两个方法,用于添加事件和删除事件处理程序的操作:addEventListener()和removeEventListener()。所有DOM节点中都包含这两个方法,并且它们都接受3个参数;事件名、函数、冒泡或捕获的布尔值(true表示捕获,false表示冒泡)。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
window.addEventListener('load', function () {
alert('Lee');
}, false);
window.addEventListener('load', function () {
alert('Mr.Lee');
}, false);
</script>
</code></pre></div></div>
<p>W3C的现代事件绑定比我们自定义的好处就是:1.不需要自定义了;2.可以屏蔽相同的函数;3.可以设置冒泡和捕获。
window.addEventListener(‘load’, init, false);//第一次执行了
window.addEventListener(‘load’, init, false);//第二次被屏蔽了</p>
<h2 id="ie事件处理函数">IE事件处理函数</h2>
<p>IE实现了与DOM中类似的两个方法:attachEvent()和detachEvent()。这两个方法接受相同的参数:事件名称和函数。</p>
<p>在使用这两组函数的时候,先把区别说一下:</p>
<ul>
<li>IE不支持捕获,只支持冒泡;</li>
<li>IE添加事件不能屏蔽重复的函数;</li>
<li>IE中的this指向的是window而不是DOM对象。</li>
<li>在传统事件上,IE是无法接受到event对象的,但使用了attchEvent()却可以,但有些区别。</li>
</ul>
<p>函数重复问题</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = document.getElementById("outdiv");
box.attachEvent('onclick', init);
box.attachEvent('onclick', init);
function init(){
alert("init")
}
</script>
</code></pre></div></div>
<p>this问题</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = document.getElementById("outdiv");
box.attachEvent('onclick', function () {
alert(this === window);//this指向的window
});
box.attachEvent('onclick', function () {
toBlue.call(box);//可以把this直接call过去
});
</script>
</code></pre></div></div>
<p>event对象传参</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = document.getElementById("outdiv");
box.onclick = function (evt) {
alert(evt);//undefined
};
//定义了传统事件后,还可以继续绑定事件,不会覆盖
box.attachEvent('onclick', function (evt) {
alert(evt);//object
alert(evt.type);//click
});
</script>
</code></pre></div></div>
<p>PS:IE中的事件绑定函数attachEvent()和detachEvent()可能在实践中不去使用,有几个原因:1.IE9就将全面支持W3C中的事件绑定函数;2.IE的事件绑定函数无法传递this;3.IE的事件绑定函数不支持捕获;4.同一个函数注册绑定后,没有屏蔽掉;5.有内存泄漏的问题。</p>
<h2 id="事件对象的其他补充">事件对象的其他补充</h2>
<p>relatedTarget属性</p>
<p>在W3C提供了一个属性:relatedTarget;这个属性可以在mouseover和mouseout事件中获取从哪里移入和从哪里移出的DOM对象。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = document.getElementById("indiv");
box.onmouseover = function (evt) {//鼠标移入box
console.log(evt.relatedTarget);//获取移入box最近的那个元素对象
}
box.onmouseout = function (evt) {//鼠标移出box
console.log(evt.relatedTarget);//获取移出box最近的那个元素对象
}
</script>
</code></pre></div></div>
<p>IE提供了两组分别用于移入移出的属性:fromElement和toElement,分别对应mouseover和mouseout。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = document.getElementById("indiv");
box.onmouseover = function (evt) {//鼠标移入box
console.log(window.event.fromElement.tagName);//获取移入box最近的那个元素对象span
}
box.onmouseout = function (evt) {//鼠标移入box
console.log(window.event.toElement.tagName);//获取移入box最近的那个元素对象span
}
</script>
</code></pre></div></div>
<p>组织浏览器默认行为</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
link.onclick = function () {
alert('Lee');
return false;//直接给个假,就不会跳转了。
};
link.onclick = function (evt) {
evt.preventDefault();//W3C,阻止默认行为,放哪里都可以
alert('Lee');
};
link.onclick = function (evt) { //IE,阻止默认行为
window.event.returnValue = false;
alert('Lee');
};
</script>
</code></pre></div></div>
<p>阻止右键菜单</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
document.addEventListener("contextmenu",function(event){
event.preventDefault();
console.log("hehe");
},false);
</script>
</code></pre></div></div>
<p>卸载前事件:beforeunload</p>
<p>用beforeunload事件,在某些浏览器上(chrome、ie、firefox)可以监听到浏览器关闭操作,能够在关闭之前,弹出一个对话框,让用户选择是否关闭</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = '确定离开此页吗?本页不需要刷新或后退';
(e || window.event).returnValue = confirmationMessage; // Gecko and Trident
return confirmationMessage;// Gecko and WebKit
});
</script>
</code></pre></div></div>
javascript笔记--(第二十一章)动态加载脚本和样式
2017-06-28T09:40:55+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第二十一章)动态加载脚本和样式
<h2 id="动态脚本">动态脚本</h2>
<h3 id="动态加载js">动态加载js</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var flag = true;//设置true再加载
if (flag) {
loadScript('test.js');//设置加载的js
}
function loadScript(url) {
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
//document.head.appendChild(script);//document.head表示<head>
document.getElementsByTagName('head')[0].appendChild(script);
}
</script>
</code></pre></div></div>
<h3 id="动态执行js">动态执行js</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var script = document.createElement('script');
script.type = 'text/javascript';
var text = document.createTextNode("alert('Lee')");
//script.appendChild(text);//IE浏览器会报错,兼容用下面的语句
script.text = "alert('hehe')"
document.getElementsByTagName('head')[0].appendChild(script);
</script>
</code></pre></div></div>
<h2 id="动态样式">动态样式</h2>
<p>样式表有两种方式进行加载,一种是<link>标签,一种是<style>标签。</p>
<h3 id="动态加载link">动态加载link</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var flag = true;
if (flag) {
loadStyles('basic.css');
}
function loadStyles(url) {
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = url;
document.getElementsByTagName('head')[0].appendChild(link);
}
</script>
</code></pre></div></div>
<h3 id="动态执行style">动态执行style</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var flag = true;
if (flag) {
var style = document.createElement('style');
style.type = 'text/css';
//var box= document.createTextNode('#box{background:red}'); IE不支持
//style.appendChild(box);
document.getElementsByTagName('head')[0].appendChild(style);
insertRule(document.styleSheets[0], 'body', 'background:red', 0);
}
function insertRule(sheet, selectorText, cssText, position) {
//如果是非IE
if (sheet.insertRule) {
sheet.insertRule(selectorText + "{" + cssText + "}", position);
//如果是IE
} else if (sheet.addRule) {
sheet.addRule(selectorText, cssText, position);
}
}
</script>
</code></pre></div></div>
javascript笔记--(第二十章)DOM元素尺寸和位置
2017-06-28T09:26:59+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第二十章)DOM元素尺寸和位置
<h2 id="获取元素css大小">获取元素CSS大小</h2>
<h3 id="通过style内联获取元素的大小">通过style内联获取元素的大小</h3>
<p>style获取只能获取到行内style属性的CSS样式中的宽和高,如果行内样式有宽高则获取;如果没有则返回空。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="box" style="width:100px;"></div>
</body>
<script type="text/javascript">
var box = document.getElementById('box');
console.log(box.style.width);//200px
console.log(box.style.height);//??
</script>
</html>
</code></pre></div></div>
<h3 id="通过计算获取元素的大小">通过计算获取元素的大小</h3>
<p>通过计算获取元素的大小,无关你是否是行内、内联或者链接,它经过计算后得到的结果返回出来。如果本身设置大小,它会返回元素的大小,如果本身没有设置,非IE浏览器会返回默认的大小,IE浏览器返回auto。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#box{
height:200px;
}
</style>
</head>
<body>
<div id="box" style="width:100px;"></div>
</body>
<script type="text/javascript">
var box = document.getElementById("box");
var style = window.getComputedStyle ?
window.getComputedStyle(box, null) : null || box.currentStyle;
console.log(style.width);//100px
console.log(style.height);//200px
</script>
</html>
</code></pre></div></div>
<h3 id="通过css规则获取元素大小">通过css规则获取元素大小</h3>
<p>cssRules(或rules)只能获取到内联和链接样式的宽和高,不能获取到行内和计算后的样式</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#box{
height:200px;
}
</style>
</head>
<body>
<div id="box" style="width:100px;"></div>
</body>
<script type="text/javascript">
var sheet = document.styleSheets[0];//获取link或style
var rule = (sheet.cssRules || sheet.rules)[0];//获取第一条规则
console.log(rule.style.width);//空
console.log(rule.style.height);//200px
</script>
</html>
</code></pre></div></div>
<p>总结:以上的三种CSS获取元素大小的方法,只能获取元素的CSS大小,却无法获取元素本身实际的大小。比如加上了内边距、滚动条、边框之类的。</p>
<h2 id="获取元素实际大小">获取元素实际大小</h2>
<h3 id="clientwidth和clientheight">clientWidth和clientHeight</h3>
<p>是对象的可见宽和高,不包括滚动条等边线,会随窗口的显示大小改变。返回元素大小,但没有单位,默认单位是px,如果你强行设置了单位,比如100em之类,它还是会返回px的大小</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="box" style="width:100px;padding:10px;border:5px"></div>
</body>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.clientWidth);//120
console.log(box.clientHeight);//20
</script>
</html>
</code></pre></div></div>
<p>如果说没有设置任何CSS的宽和高度,那么非IE浏览器会算上滚动条和内边距的计算后的大小,而IE浏览器则返回0</p>
<h3 id="scrollwidth和scrollheight">scrollWidth和scrollHeight</h3>
<p>是对象的实际内容的宽和高,不包边线宽度,会随对象中内容的多少改变</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="box" style="border:5px solid red;box-sizing:border-box;width:100px;overflow-y: auto">
test test test test test test test test test
</div>
</body>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.scrollWidth);//90
console.log(box.scrollHeight);//90
</script>
</html>
</code></pre></div></div>
<p>如果没有设置任何CSS的宽和高度,它会得到计算后的宽度和高度。</p>
<h3 id="offsetwidth和offsetheight">offsetWidth和offsetHeight</h3>
<p>是对象的可见宽和高,包滚动条等边线,会随窗口的显示大小改变。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="box" style="width:100px;padding:10px;border:5px solid red;">aa</div>
</body>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.offsetWidth);//130
console.log(box.offsetHeight);//48
</script>
</html>
</code></pre></div></div>
<p>如果没有设置任何CSS的宽和高度,他会得到计算后的宽度和高度</p>
<h2 id="获取元素周边大小">获取元素周边大小</h2>
<h3 id="clientleft和clienttop">clientLeft和clientTop</h3>
<p>这组属性可以获取元素设置了左边框和上边框的大小</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body style="margin:0">
<div id="box" style="width:100px;padding:10px;border:5px solid red;border-top-width:10px">aa</div>
</body>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.clientLeft);//5
console.log(box.clientTop);//10
</script>
</html>
</code></pre></div></div>
<h3 id="offsetleft和offsettop">offsetLeft和offsetTop</h3>
<p>这组属性可以获取当前元素相对于父元素的位置</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body style="margin:0;padding: 8px 16px;position: relative;">
<div id="box" style="width:100px;padding:10px;border:5px solid red;border-top-width:10px">aa</div>
<div id="box1" style="position: absolute;left:40px;top: 30px"></div>
</body>
<script type="text/javascript">
var box = document.getElementById("box");
console.log(box.offsetLeft);//16
console.log(box.offsetTop);//8
var box1 = document.getElementById("box1");
console.log(box1.offsetLeft);//40
console.log(box1.offsetTop);//30
</script>
</html>
</code></pre></div></div>
<p>获取元素当前相对于父元素的位置,最好将它设置为定位position:absolute;否则不同的浏览器会有不同的解释</p>
<h3 id="scrolltop和scrollleft">scrollTop和scrollLeft</h3>
<p>这组属性可以获取滚动条被隐藏的区域大小(即元素中的内容超出元素上边界或者左边界的那部分),也可设置定位到该区域。</p>
<h2 id="元素位置">元素位置</h2>
<p>getBoundingClientRect()。这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body style="margin:0;padding: 8px 16px;position: relative;">
<div id="box" style="width:100px;padding:10px;border:5px solid red;border-top-width:10px">aa</div>
<div id="box1" style="position: absolute;left:40px;top: 30px;width:50px"></div>
</body>
<script type="text/javascript">
var box = document.getElementById('box');//获取元素
console.log(box.getBoundingClientRect().top);//8,元素上边距离页面上边的距离
console.log(box.getBoundingClientRect().right);//146,元素右边距离页面左边的距离
console.log(box.getBoundingClientRect().bottom);//61,元素下边距离页面上边的距离
console.log(box.getBoundingClientRect().left);//16,元素左边距离页面左边的距离
var box1 = document.getElementById('box1');
console.log(box1.getBoundingClientRect().top);//30
console.log(box1.getBoundingClientRect().right);//90
console.log(box1.getBoundingClientRect().bottom);//30
console.log(box1.getBoundingClientRect().left);//40
</script>
</html>
</code></pre></div></div>
<p>注意:IE、Firefox3+、Opera9.5、Chrome、Safari支持,在IE中,默认坐标从(2,2)开始计算,导致最终距离比其他浏览器多出两个像素</p>
javascript笔记--(第十九章)DOM操作表格及样式
2017-06-28T09:17:26+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第十九章)DOM操作表格及样式
<h2 id="table对象">Table对象</h2>
<p>常用集合</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:155px; background-color:rgb(213,213,213)">
集合
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/coll_table_cells.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">cells[]</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
返回包含表格中所有单元格的一个数组。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/coll_table_rows.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">rows[]</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
返回包含表格中所有行的一个数组。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
tBodies[]
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
返回包含表格中所有 tbody 的一个数组。
</td>
</tr>
</tbody>
</table>
<p>常用属性</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:155px; background-color:rgb(213,213,213)">
属性
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_table_caption.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">caption</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
对表格的 <caption> 元素的引用。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
tFoot
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
返回表格的 TFoot 对象。如果不存在该元素,则为 null。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
tHead
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
返回表格的 THead 对象。如果不存在该元素,则为 null。
</td>
</tr>
</tbody>
</table>
<p>常用方法</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:155px; background-color:rgb(213,213,213)">
方法
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_table_createcaption.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">createCaption()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
为表格创建一个 caption 元素。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_table_createtfoot.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">createTFoot()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
在表格中创建一个空的 tFoot 元素。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_table_createthead.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">createTHead()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
在表格中创建一个空的 tHead 元素。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_table_deletecaption.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">deleteCaption()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
从表格删除 caption 元素以及其内容。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_table_deleterow.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">deleteRow()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
从表格删除一行。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_table_deletetfoot.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">deleteTFoot()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
从表格删除 tFoot 元素及其内容。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_table_deletethead.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">deleteTHead()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
从表格删除 tHead 元素及其内容。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_table_insertrow.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">insertRow()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
在表格中插入一个新行。
</td>
</tr>
</tbody>
</table>
<p>table操作</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var table = document.createElement('table');
table.border = 1;
table.width = 300;
var caption = table.createCaption();
caption.innerHTML = "人员表"
table.appendChild(caption);
var thead = table.createTHead();//crate后就自动添加到table里了
var tr1 = thead.insertRow(0);//插入tr
var td1_1 = tr1.insertCell(0);
var td1_2 = tr1.insertCell(1);
td1_1.innerHTML = "tr1.insertCell_td1_1";
td1_2.innerHTML = "tr1.insertCell_td1_2";
var tr2 = table.insertRow(0);//tr集合的第一个位置,包括thead,tbody,tfoot的tr
var td2_1 = tr2.insertCell(0);//插入td
var td2_2 = tr2.insertCell(1);
td2_1.innerHTML = "tr2.insertCell_td2_1";
td2_2.innerHTML = "tr2.insertCell_td2_2";
tr2.deleteCell(1);//删除第二个td
var tbody = document.createElement("tbody");//table没有createTBody方法
var tr3 = tbody.insertRow();
var td3_1 = tr3.insertCell(0);
var td3_2 = tr3.insertCell(1);
td3_1.innerHTML = "tr3.insertCell_td3_1";
td3_2.innerHTML = "tr3.insertCell_td3_2";
table.appendChild(tbody);//需要手动append,这个tbody会在tfoot之后
var tfoot = table.createTFoot();//crate后就自动添加到table里了
var tr4 = tfoot.insertRow();
var td4_1 = tr4.insertCell(0);
var td4_2 = tr4.insertCell(1);
td4_1.innerHTML = "tr4.insertCell_td4_1";
td4_2.innerHTML = "tr4.insertCell_td4_2";
tfoot.deleteRow(0);//删除tfoot第一个tr
table.deleteRow(0);//删除tr集合中的第一行
table.deleteCaption();//删除caption
table.deleteTHead();//删除table的thead
table.deleteTFoot();//删除table的tfoot
document.body.appendChild(table);
</script>
</code></pre></div></div>
<h2 id="样式">样式</h2>
<h3 id="访问元素的样式">访问元素的样式</h3>
<p>任何HTML元素标签都会有一个通用的属性:style。它会返回CSSStypeDeclaration对象。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="box" style="color:red;font-size:12px;"></div>
</body>
<script type="text/javascript">
var box = document.getElementById('box');//获取box
console.log(box.style);//CSSStyleDeclaration
console.log(box.style.color);//red
console.log(box.style.fontSize);//12px
box.style.setProperty("border","1px");//添加和设置属性
box.style.removeProperty('color');//移除某个熟悉
box.style.cssText = "background-color:blue";//设置style属性
console.log(box.style.backgroundColor);//blue
</script>
</html>
</code></pre></div></div>
<p>getComputedStyle()和currentStyle能获取行内样式,内嵌样式或者外部样式,不过只可以读</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#box{
color:red;font-size:12px;
}
</style>
</head>
<body>
<div id="box" style=""></div>
</body>
<script type="text/javascript">
var box = document.getElementById('box');//获取box
var style = window.getComputedStyle ?
window.getComputedStyle(box, null) : null || box.currentStyle;
console.log(style.color);//rgb(255, 0, 0);
style.cssText = "background-color:blue";//报错
</script>
</html>
</code></pre></div></div>
<h3 id="操作样式表">操作样式表</h3>
<p>添加删除className</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = document.getElementById('box');//获取box
//判断是否存在这个class
function hasClass(element, className) {
return element.className.match(new RegExp('(\\s|^)'+className+'(\\s|$)'));
}
//添加一个class,如果不存在的话
function addClass(element, className) {
if (!hasClass(element, className)) {
element.className += " "+className;
}
}
//删除一个class,如果存在的话
function removeClass(element, className) {
if (hasClass(element, className)) {
element.className = element.className.replace(new RegExp('(\\s|^)'+className+'(\\s|$)'),' ');
}
}
addClass(box,"class1");
addClass(box,"class2");
removeClass(box,"class1");
</script>
</code></pre></div></div>
<p>添加删除css规则</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
#box{
color:red;font-size:12px;
}
</style>
</head>
<body>
<div id="box"></div>
</body>
<script type="text/javascript">
//为了添加CSS规则,并且兼容所有浏览器,我们必须写一个函数:
var sheet = document.styleSheets[0];
/*
//也可以通过以下方式获取相应sheet
var link = document.getElementsByTagName('link')[0]; //HTMLLinkElement
var style = document.getElementsByTagName('style')[0]; //HTMLStyleElement
var sheet = style.sheet || style.styleSheet;
var sheet = link.sheet || link.styleSheet;
*/
var rules = sheet.cssRules || sheet.rules;
console.log(rules[0].selectorText);//#box
console.log(rules[0].style.color);//red
console.log(rules[0].cssText);//#box { color: red; font-size: 12px; }
rules[0].cssText = "#box {background-color:red}";//无效
function insertRule(sheet, selectorText, cssText, position) {
//如果是非IE
if (sheet.insertRule) {
sheet.insertRule(selectorText + "{" + cssText + "}", position);
//如果是IE
} else if (sheet.addRule) {
sheet.addRule(selectorText, cssText, position);
}
}
insertRule(sheet, "#box", "background-color:red;", 0);//在第一个位置新建一个规则
console.log(rules[0].selectorText);//#box
console.log(rules[0].style.backgroundColor);//red
//为了删除CSS规则,并且兼容所有浏览器,我们必须写一个函数:
function deleteRule(sheet, index) {
//如果是非IE
if (sheet.deleteRule) {
sheet.deleteRule(index);
//如果是IE
} else if (sheet.removeRule) {
sheet.removeRule(index);
}
}
deleteRule(sheet, 0);//删除第一个规则
console.log(rules[0].selectorText);//#box
console.log(rules[0].style.color);//red
</script>
</html>
</code></pre></div></div>
<p>总结:三种操作CSS的方法,第一种可操作style行内样式,可读可写;第二种可操作行内、内联和链接,使用getComputedStyle或currentStyle,可读不可写;第三种cssRules或rules,可操作内联和链接,可读可写。</p>
javascript笔记--(第十八章)常用DOM操作
2017-06-28T09:01:55+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第十八章)常用DOM操作
<h2 id="dom">DOM</h2>
<p>在 HTML DOM 中,所有事物都是节点。DOM 是被视为节点树的 HTML。</p>
<h3 id="主要有以下几种dom类型">主要有以下几种DOM类型:</h3>
<table class="dataintable " style="margin: 15px 0px 0px; padding: 0px; border: 1px solid rgb(170, 170, 170); border-collapse: collapse; width: 485px; font-family: PingFangSC-Regular, Verdana, Arial, 微软雅黑, 宋体; font-size: 14px; background-color: rgb(253, 252, 248);">
<tbody style="margin: 0px; padding: 0px; border: 0px;">
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<th style="margin: 0px; padding: 5px 15px 5px 6px; border: 1px solid rgb(63, 63, 63); vertical-align: baseline; background-color: rgb(63, 63, 63); text-align: left; color: rgb(255, 255, 255);">
元素类型
</th>
<th style="margin: 0px; padding: 5px 15px 5px 6px; border: 1px solid rgb(63, 63, 63); vertical-align: baseline; background-color: rgb(63, 63, 63); text-align: left; color: rgb(255, 255, 255);">
NodeType
</th>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
元素
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
1
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
属性
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
2
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
文本
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
3
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
注释
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
8
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
文档
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
9
</td>
</tr>
</tbody>
</table>
<h3 id="常用方法">常用方法:</h3>
<table class="dataintable " style="margin: 15px 0px 0px; padding: 0px; border: 1px solid rgb(170, 170, 170); border-collapse: collapse; width: 809px;">
<tbody style="margin: 0px; padding: 0px; border: 0px;">
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<th style="margin: 0px; padding: 5px 15px 5px 6px; border: 1px solid rgb(63, 63, 63); vertical-align: baseline; background-color: rgb(63, 63, 63); text-align: left; color: rgb(255, 255, 255);">
方法
</th>
<th style="margin: 0px; padding: 5px 15px 5px 6px; border: 1px solid rgb(63, 63, 63); vertical-align: baseline; background-color: rgb(63, 63, 63); text-align: left; color: rgb(255, 255, 255);">
描述
</th>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
getElementById()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
返回带有指定 ID 的元素。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
getElementsByTagName()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
返回包含带有指定标签名称的所有元素的节点列表(集合/节点数组)。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
getElementsByClassName()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
返回包含带有指定类名的所有元素的节点列表。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
appendChild()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
把新的子节点添加到指定节点。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
removeChild()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
删除子节点。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
replaceChild()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
替换子节点。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
insertBefore()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
在指定的子节点前面插入新的子节点。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
createAttribute()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
创建属性节点。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
createElement()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
创建元素节点。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
createTextNode()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
创建文本节点。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(255, 255, 255);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
getAttribute()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
返回指定的属性值。
</td>
</tr>
<tr style="margin: 0px; padding: 0px; border: 0px; background-color: rgb(245, 245, 245);">
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
setAttribute()
</td>
<td style="margin: 0px; padding: 6px 15px 6px 6px; border: 1px solid rgb(170, 170, 170); vertical-align: text-top;">
把指定属性设置或修改为指定的值。
</td>
</tr>
</tbody>
</table>
<h3 id="属性操作">属性操作:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div style="color:black" id="box" title="mytitle" class="class" bbb="bbb_value">
hello
</div>
<input id="input" type="text" value="123"/>
<input id="input1" type="radio" checked/>
</body>
<script type="text/javascript">
document.getElementById('box').id;//获取id
//document.getElementById('box').id = 'person';//设置id
document.getElementById('box').title;//获取title
document.getElementById('box').title = 'new_title';//设置title
document.getElementById('box').style;//获取CSSStyleDeclaration对象
document.getElementById('box').style.color;//获取style对象中color的值
document.getElementById('box').style.color = 'red';//设置style对象中color的值
document.getElementById('box').className;//获取class
document.getElementById('box').className = 'box';//设置class
document.getElementById('box').getAttribute('className');//非IE不支持
console.log(document.getElementById('box').bbb);//获取自定义属性的值,非IE不支持
document.getElementById('box').setAttribute("bbb","new_bbb_value");
console.log(document.getElementById('box').getAttribute("bbb"));//new__bbb_value
document.getElementById('box').removeAttribute("bbb");//删除属性
console.log(document.getElementById('box').getAttribute("bbb"));//null
console.log(document.getElementById('input').value);//1234
console.log(document.getElementById('input1').checked);//true
</script>
</html>
</code></pre></div></div>
<h3 id="节点层次">节点层次:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div style="color:black" id="box" title="mytitle" class="class" bbb="bbb_value">
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
</div>
</body>
<script type="text/javascript">
var div = document.getElementById('box')
console.log(div.innerHTML);
/*
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
*/
console.log(div.childNodes.length);//得到子节点个数,IE3个,非IE7个,换行会产生空白节点
console.log(div.childNodes[0].nodeValue);//输出空白
console.log(div.attributes['bbb'].nodeValue);//bbb_value
console.log(div.attributes.getNamedItem('bbb').nodeValue);//和上面效果一样
console.log(div.firstChild.nodeValue);//输出空白
console.log(div.firstChild.innerHTML);//undefined
console.log(div.lastChild.nodeValue);//输出空白
console.log(div.ownerDocument);//#document
console.log(div.childNodes[0].nextSibling.innerHTML);//hello1
console.log(div.childNodes[2].previousSibling.innerHTML);//hello2
console.log(div.parentNode);//body对象
</script>
</html>
</code></pre></div></div>
<p>注意:在获取到文本节点的时候,是无法使用innerHTML这个属性输出文本内容的。这个非标准的属性必须在获取元素节点的时候,才能输出里面包含的文本;在非IE中,标准的DOM具有识别空白文本节点的功能,所以在火狐浏览器是7个,而IE自动忽略了,如果要保持一致的子元素节点,需要手工忽略掉它。</p>
<h3 id="节点操作">节点操作:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
</body>
<script type="text/javascript">
document.write("<div id='box'></div>");
var span = document.createElement("span");
var text = document.createTextNode("hello");
span.appendChild(text);
document.getElementById("box").appendChild(span);
var h = document.createElement("h1");
var text1 = document.createTextNode("h1");
h.appendChild(text1);
document.getElementById("box").insertBefore(h,span);
var input = null;
input = document.createElement('input');
input.setAttribute('type', 'radio');
input.setAttribute('name', 'sex');
document.getElementById("box").appendChild(input);
//替换节点
var text2 = document.createTextNode("new_hello");
span.replaceChild(text2,span.childNodes[0]);
//克隆节点
var span1 = span.cloneNode(true);//true会复制内容,否则只复制结构
span1.id = "span1";
document.getElementById("box").appendChild(span1);
//删除节点
document.getElementById("box").removeChild(document.getElementById("span1"));
</script>
</html>
</code></pre></div></div>
<h2 id="dom扩展">DOM扩展</h2>
<h3 id="呈现模式">呈现模式</h3>
<p>从IE6开始开始区分标准模式和混杂模式(怪异模式),主要是看文档的声明。IE为document对象添加了一个名为compatMode属性,这个属性可以识别IE浏览器的文档处于什么模式如果是标准模式,则返回CSS1Compat,如果是混杂模式则返回BackCompat。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
if (document.compatMode == 'CSS1Compat') {
console.log(document.documentElement.clientWidth);
} else {
console.log(document.body.clientWidth);
}
</script>
</code></pre></div></div>
<p>后来Firefox、Opera和Chrome都实现了这个属性。从IE8后,又引入documentMode新属性,因为IE8有3种呈现模式分别为标准模式8,仿真模式7,混杂模式5。所以如果想测试IE8的标准模式,就判断document.documentMode > 7 即可。</p>
<h3 id="滚动">滚动</h3>
<p>scrollIntoView(alignWithTop) 函数用来滚动浏览器窗口或容器元素,以便在当前视窗的可见范围看见当前元素。如果alignWithTop为true,或者省略它,窗口会尽可能滚动到自身顶部与元素顶部平齐</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<a onClick="onc()" hef="#">click here</a>
<div style="height:400px; background-color:blue"></div>
<div id="nn" style="background-color: red;height:900px;"></div>
</body>
<script type="text/javascript">
//作为一个事件的函数来被调用
function onc () {
var dd = document.getElementById("nn").scrollIntoView(true);//这个意思其实就是将这个元素滚动到浏览器窗口的顶部来显示
}
</script>
</html>
</code></pre></div></div>
<h3 id="children属性">children属性</h3>
<p>由于子节点空白问题,IE和其他浏览器解释不一致。虽然可以过滤掉,但如果只是想得到有效子节点,可以使用children属性,几乎所有浏览器都支持。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div">
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
</div>
</body>
<script type="text/javascript">
console.log(document.getElementById("div").children.length);//3
console.log(document.getElementById("div").children[0].innerHTML);//hello1
</script>
</html>
</code></pre></div></div>
<h3 id="contains方法">contains()方法</h3>
<p>判断一个节点是不是另一个节点的后代,我们可以使用contains()方法。这个方法是IE率先使用的,开发人员无须遍历即可获取此信息</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var div = document.getElementById("div")
console.log(div.contains(div.firstChild));//true
</script>
</code></pre></div></div>
<p>早期的Firefox不支持这个方法,新版的支持了,其他浏览器也都支持,Safari2.x浏览器支持的有问题,无法使用。所以,必须做兼容</p>
<p>在Firefox的DOM3级实现中提供了一个替代的方法compareDocumentPosition()方法。这个方法确定两个节点之间的关系。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var div = document.getElementById("div")
console.log(div.compareDocumentPosition(div.firstChild));//20
</script>
</code></pre></div></div>
<h3 id="innertext属性">innerText属性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div">
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
</div>
</body>
<script type="text/javascript">
var div = document.getElementById("div")
console.log(div.innerText);//获取文本内容(如有html直接过滤掉)
div.innerText = 'Mr.Lee';//设置文本(如有html转义)
//DOM3新属性
console.log(div.textContent)
div.innerText = '<html>';
</script>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十八章)常用DOM操作-1.jpg" alt="" /></p>
<h3 id="innerhtml属性">innerHTML属性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
document.getElementById('div').innerHTML;//获取文本(不过滤HTML)
document.getElementById('div').innerHTML = '<b>123</b>';//可解析HTML
</script>
</code></pre></div></div>
<p>虽然innerHTML可以插入HTML,但本身还是有一定的限制,也就是所谓的作用域元素,离开这个作用域就无效了</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
document.getElementById("div").innerHTML = "<script>alert('Lee');</script"+">";//<script>元素不能被执行
</script>
</code></pre></div></div>
<h3 id="outertext属性">outerText属性</h3>
<p>outerText在取值的时候和innerText一样,但是赋值方法相当危险,他不单替换了文本内容,还将元素直接抹去。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="div">
<span>hello1</span>
<span>hello2</span>
<span>hello3</span>
</div>
</body>
<script type="text/javascript">
var div = document.getElementById("div")
console.log(div.outerText);//获取文本内容(如有html直接过滤掉)
div.outerText = 'Mr.Lee';//设置文本(如有html转义)
console.log(document.getElementById("div"));//null
</script>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十八章)常用DOM操作-2.jpg" alt="" /></p>
<h3 id="outerhtml属性">outerHTML属性</h3>
<p>outerHTML属性在取值和innerHTML一致,但和outerText也一样,很危险,赋值的之后会将元素抹去。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var div = document.getElementById("div")
console.log(div.outerHTML);//获取文本内容(如有html直接过滤掉)
div.outerHTML = '<b>124</b>';//设置文本(如有html转义)
console.log(document.getElementById("div"));//null
</script>
</code></pre></div></div>
<p>关于最常用的innerHTML属性和节点操作方法的比较,在插入大量HTML标记时使用innerHTML的效率明显要高很多。因为在设置innerHTML时,会创建一个HTML解析器。这个解析器是浏览器级别的(C++编写),因此执行JavaScript会快的多。但,创建和销毁HTML解析器也会带来性能损失。最好控制在最合理的范围内,如下:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">i</span> <span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">ul</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="dl">'</span><span class="s1"><li>item</li></span><span class="dl">'</span><span class="p">;</span><span class="c1">//避免频繁</span>
<span class="p">}</span>
<span class="c1">//改</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">10</span><span class="p">;</span> <span class="nx">i</span> <span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">a</span> <span class="o">=</span> <span class="dl">'</span><span class="s1"><li>item</li></span><span class="dl">'</span><span class="p">;</span><span class="c1">//临时保存</span>
<span class="p">}</span>
<span class="nx">ul</span><span class="p">.</span><span class="nx">innerHTML</span> <span class="o">=</span> <span class="nx">a</span><span class="p">;</span>
</code></pre></div></div>
javascript笔记--(第十七章)BOM
2017-06-28T08:05:51+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第十七章)BOM
<h2 id="bom">BOM</h2>
<p>BOM也叫浏览器对象模型,它提供了很多对象,用于访问浏览器的功能。BOM缺少规范,每个浏览器提供商又按照自己想法去扩展它,那么浏览器共有对象就成了事实的标准。所以,BOM本身是没有标准的或者还没有哪个组织去标准它。</p>
<h2 id="window对象">window对象</h2>
<p>BOM的核心对象是window,它表示浏览器的一个实例。window对象处于JavaScript结构的最顶层,对于每个打开的窗口,系统都会自动为其定义 window 对象。
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十七章)BOM-1.jpg" alt="" /></p>
<h2 id="新建窗口">新建窗口</h2>
<p>open() 方法用于打开一个新的浏览器窗口或查找一个已命名的窗口。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">//window.open(URL,name,features,replace)//repalce为true将替换历史中的当前条目,否则新建条目</span>
<span class="nx">open</span><span class="p">(</span><span class="dl">'</span><span class="s1">http://www.baidu.com</span><span class="dl">'</span><span class="p">);</span><span class="c1">//新建页面并打开百度</span>
<span class="nx">open</span><span class="p">(</span><span class="dl">'</span><span class="s1">http://www.baidu.com</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">baidu</span><span class="dl">'</span><span class="p">);</span><span class="c1">//新建页面并命名窗口并打开百度</span>
<span class="nx">open</span><span class="p">(</span><span class="dl">'</span><span class="s1">http://www.baidu.com</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">_parent</span><span class="dl">'</span><span class="p">);</span><span class="c1">//在本页窗口打开百度,_blank是新建</span>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
//示例1
function open_win()
{
window.open("child.html","new_win","width=400,height=400",true);
}
open_win()
//示例2
var myWindow=window.open('','MyName','width=200,height=100')
myWindow.document.write("This is 'myWindow'")
console.log(myWindow.closed);//false
myWindow.focus();
myWindow.close();
console.log(myWindow.closed);//true
myWindow.opener.document.write("This is the parent window")
console.log(window.closed);//false
</script>
</code></pre></div></div>
<p>注意:只有表示顶层窗口的 Window 对象的 operner 属性才有效,表示框架的 Window 对象的 operner 属性无效</p>
<h2 id="浏览器窗口位置和尺寸">浏览器窗口位置和尺寸</h2>
<p>IE、Safari、Opera和Chrome都提供了screenLeft和screenTop属性,分别用于表示窗口相对于屏幕左边和上边的位置。Firefox则在screenX和screenY属性中提供相同的窗口位置信息,Safari和Chrome也同时支持这两个属性。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
console.log(window.screenLeft);
console.log(window.screenX);
console.log(window.screenTop);
console.log(window.screenY);
</script>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十七章)BOM-2.jpg" alt="" /></p>
<p>注意:screenX,screenY是以红色区域的左上角为基准,其相对于屏幕左上角的距离</p>
<p>innerWidth和innerHeight,返回浏览器窗口本身的尺寸;outerWidth和outerHeight,返回浏览器窗口本身及边框的尺寸。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
console.log(window.innerWidth);
console.log(window.innerHeight);
console.log(window.outerWidth);
console.log(window.outerHeight);
</script>
</script>
</head>
<body>
<div style="height:1000px"></div>
</body>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十七章)BOM-3.jpg" alt="" /></p>
<p>红色区域代表了innerWidth和innerHeight,蓝色区域代表了outerWidth和outerHeight</p>
<p>IE没有提供当前浏览器窗口尺寸的属性;不过,在后面的DOM课程中有提供相关的方法。</p>
<h2 id="页面窗口尺寸">页面窗口尺寸</h2>
<p>在IE以及Firefox、Safari、Opera和Chrome中,document.documentElement.clientWidth和document.documentElement.clientHeight中保存了页面窗口的信息。在IE6中,这些属性必须在标准模式下才有效;如果是怪异模式,就必须通过document.body.clientWidth和document.body.clientHeight取得相同的信息。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>Document</title>
<script type="text/javascript">
//如果是Firefox浏览器,直接使用innerWidth和innerHeight
//var width = window.innerWidth; //这里要加window,因为IE会无效
//var height = window.innerHeight;
if (typeof width != 'number') { //如果是IE,就使用document
if (document.compatMode == 'CSS1Compat') {
width = document.documentElement.clientWidth;
height = document.documentElement.clientHeight;
} else {
width = document.body.clientWidth; //非标准模式使用body
height = document.body.clientHeight;
}
}
console.log(width);
console.log(height);
</script>
</head>
<body>
<div style="height:1000px"></div>
</body>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十七章)BOM-4.jpg" alt="" />
红色区域代表了document.documentElement.clientWidth和document.documentElement.clientHeight,可以看到,document.documentElement.clientWidth和document.documentElement.clientHeight获取的值和innerWidth和innerHeight是一样的</p>
<h2 id="定时器">定时器</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var timeId = setTimeout(function(name,age){
console.log(name+":"+age);//lisong:26
},100,"lisong",26);
//clearTimeout(timeId);
var intervalId = setInterval(function(name,age){
console.log(name+":"+age);//lisong1:26
},1000,"lisong1",26);
//clearTimeout(intervalId);
</script>
</code></pre></div></div>
<h2 id="location对象">location对象</h2>
<p>提供了与当前窗口中加载的文档有关的信息,还提供了一些导航功能。事实上,location对象是window对象的属性,也是document对象的属性;所以window.location和document.location等效。</p>
<p>location属性</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:190px; background-color:rgb(213,213,213)">
属性
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_loc_hash.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">hash</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
设置或返回从井号 (#) 开始的 URL(锚)。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_loc_host.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">host</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
设置或返回主机名和当前 URL 的端口号。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_loc_hostname.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">hostname</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
设置或返回当前 URL 的主机名。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_loc_href.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">href</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
设置或返回完整的 URL。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_loc_pathname.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">pathname</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
设置或返回当前 URL 的路径部分。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_loc_port.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">port</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
设置或返回当前 URL 的端口号。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_loc_protocol.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">protocol</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
设置或返回当前 URL 的协议。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_loc_search.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">search</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
设置或返回从问号 (?) 开始的 URL(查询部分)。
</td>
</tr>
</tbody>
</table>
<p>location方法</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_loc_assign.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">assign()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
加载新的文档。
</td>
</tr>
</tbody>
</table>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
location.hash = '#1'; //设置#后的字符串,并跳转
console.log(location.hash); //获取#后的字符串
location.port = 8888; //设置端口号,并跳转
console.log(location.port); //获取当前端口号,
location.hostname = 'Lee'; //设置主机名,并跳转
console.log(location.hostname); //获取当前主机名,
location.pathname = 'Lee'; //设置当前路径,并跳转
console.log(location.pathname); //获取当前路径,
location.protocal = 'ftp:'; //设置协议,没有跳转
console.log(location.protocol); //获取当前协议
location.search = '?id=5'; //设置?后的字符串,并跳转
console.log(location.search); //获取?后的字符串
location.href = 'http://www.baidu.com'; //设置跳转的URL,并跳转
console.log(location.href); //获取当前的URL*/
</script>
</code></pre></div></div>
<p>注意:上面的方法会直接改变地址栏在Web开发中,我们经常需要获取诸如?id=5&search=ok这种类型的URL的键值对,可以先获取search,再获取键值对</p>
<p>页面加载:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
location.reload();//最有效的重新加载,有可能从缓存加载
location.reload(true);//强制加载,从服务器源头重新加载
location.replace('http://www.baidu.com');//可以避免产生跳转前的历史记录
location.assign('http://www.baidu.com');//跳转到新页面,会产生新的历史
location.href = 'http://www.baidu.com'//和assign一样
</script>
</code></pre></div></div>
<h2 id="history对象">history对象</h2>
<p>history属性</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/prop_his_length.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">length</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
返回浏览器历史列表中的 URL 数量。
</td>
</tr>
</tbody>
</table>
<p>history方法</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_his_back.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">back()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
加载 history 列表中的前一个 URL。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_his_forward.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">forward()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
加载 history 列表中的下一个 URL。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/met_his_go.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">go()</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
加载 history 列表中的某个具体页面。
</td>
</tr>
</tbody>
</table>
javascript笔记--(第十六章)匿名函数和闭包
2017-06-28T07:53:30+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第十六章)匿名函数和闭包
<h2 id="匿名函数">匿名函数</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="c1">//function(){}//会报错</span>
<span class="kd">var</span> <span class="nx">fun</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span><span class="c1">//将匿名函数赋值给变量</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">arg</span><span class="p">){</span><span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arg</span><span class="p">)}(</span><span class="dl">'</span><span class="s1">test</span><span class="dl">'</span><span class="p">);</span><span class="c1">//声明的时候执行</span>
<span class="p">(</span><span class="kd">function</span><span class="p">(){})();</span><span class="c1">//匿名函数自执行</span>
<span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="kd">function</span><span class="p">(){};</span><span class="c1">//函数里的匿名函数</span>
<span class="p">}</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="闭包">闭包</h2>
<p>闭包是指有权访问另一个函数作用域中的变量的函数,创建闭包的常见的方式,就是在一个函数内部创建另一个函数,通过另一个函数访问这个函数的局部变量</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="c1">//通过闭包可以返回局部变量</span>
<span class="kd">function</span> <span class="nx">box</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">user</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="c1">//通过匿名函数返回box()局部变量</span>
<span class="k">return</span> <span class="nx">user</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">()());</span> <span class="c1">//通过box()()来直接调用匿名函数返回值</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="nx">box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">());</span> <span class="c1">//另一种调用匿名函数返回值</span>
<span class="c1">//通过闭包可以实现局部变量的累加</span>
<span class="kd">function</span> <span class="nx">box</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">age</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">age</span> <span class="o">++</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">age</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="nx">box</span><span class="p">();</span> <span class="c1">//获得函数</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">());</span> <span class="c1">//调用匿名函数</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">());</span> <span class="c1">//第二次调用匿名函数,实现累加</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>使用闭包有一个优点,也是它的缺点:就是可以把局部变量驻留在内存中,可以避免使用全局变量。(全局变量污染导致应用程序不可预测性,每个模块都可调用必将引来灾难,所以推荐使用私有的,封装的局部变量)。由于闭包里作用域返回的局部变量资源不会被立刻销毁回收,所以可能会占用更多的内存。过度使用闭包会导致性能下降,建议在非常有必要的时候才使用闭包。</p>
<h3 id="循环里的闭包">循环里的闭包</h3>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">box</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">5</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">arr</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">i</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">arr</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="nx">box</span><span class="p">();</span> <span class="c1">//得到函数数组</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span> <span class="c1">//得到函数集合长度</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">b</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">[</span><span class="nx">i</span><span class="p">]());</span> <span class="c1">//输出每个函数的值,都是最后一个值</span>
<span class="p">}</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>box()已执行完毕,i早已变成5,而返回的函数保存的变量都是i,所以最终的结果就是5个5</p>
<h3 id="循环里的闭包修改">循环里的闭包–修改</h3>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">box</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[];</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="mi">5</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">arr</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span> <span class="p">(</span><span class="nx">num</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span><span class="c1">//返回函数</span>
<span class="k">return</span> <span class="nx">num</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">})(</span><span class="nx">i</span><span class="p">);</span>
<span class="cm">/*
//相当于:
arr[i] = (function () {
var num = i;//定义一个局部变量
return function () {
return num;
}
})();
*/</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nx">arr</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="nx">box</span><span class="p">();</span> <span class="c1">//得到函数数组</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">b</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">[</span><span class="nx">i</span><span class="p">]());</span> <span class="c1">//0,1,2,3,4</span>
<span class="p">}</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>通过在box作用域里新建块级作用域来是每个返回函数保存的变量都不一样</p>
<h3 id="闭包中的this对象">闭包中的this对象</h3>
<p>闭包在运行时指向window的,因为闭包并不属于这个对象的属性或方法。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">user</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">The Window</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">user</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">The Object</span><span class="dl">'</span><span class="p">,</span>
<span class="na">getUserFunction</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="c1">//闭包不属于obj,里面的this指向window</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">user</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">getUserFunction</span><span class="p">()());</span> <span class="c1">//The window</span>
<span class="c1">//可以强制指向某个对象</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">getUserFunction</span><span class="p">().</span><span class="nx">call</span><span class="p">(</span><span class="nx">obj</span><span class="p">));</span> <span class="c1">//The Object</span>
<span class="cm">/*
//也可以从上一个作用域中得到对象
getUserFunction : function () {
var that = this; //从对象的方法里得对象
return function () {
return that.user;
};
}
*/</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="模仿块级作用域">模仿块级作用域</h2>
<p>JavaScript没有块级语句的作用域,if () {} for () {}等没有作用域</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="c1">//使用块级作用域(私有作用域)改写</span>
<span class="kd">function</span> <span class="nx">box</span><span class="p">(</span><span class="nx">count</span><span class="p">)</span> <span class="p">{</span>
<span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">for</span> <span class="p">(</span><span class="kd">var</span> <span class="nx">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o"><</span><span class="nx">count</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{}</span>
<span class="p">})();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">i</span><span class="p">);</span> <span class="c1">//报错,无法访问</span>
<span class="p">}</span>
<span class="nx">box</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>使用了块级作用域(私有作用域)后,匿名函数中定义的任何变量,都会在执行结束时被销毁。在全局作用域中使用块级作用域可以减少闭包占用的内存问题,因为没有指向匿名函数的引用。只要函数执行完毕,就可以立即销毁其作用域链了。</p>
<h2 id="私有变量">私有变量</h2>
<p>JavaScript没有私有属性的概念;所有的对象属性都是公有的。不过,却有一个私有变量的概念。任何在函数中定义的变量,都可以认为是私有变量,因为不能在函数的外部访问这些变量</p>
<p>而通过函数内部创建一个闭包,那么闭包通过自己的作用域链也可以访问这些变量。而利用这一点,可以创建用于访问私有变量的公有方法。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">age</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span> <span class="c1">//私有变量</span>
<span class="kd">function</span> <span class="nx">run</span><span class="p">()</span> <span class="p">{</span> <span class="c1">//私有函数</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">this</span><span class="p">.</span><span class="kd">get</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="c1">//对外公共的特权方法,闭包(函数访问了不属于对象作用域的age和run方法)</span>
<span class="k">return</span> <span class="nx">age</span> <span class="o">+</span> <span class="nx">run</span><span class="p">();</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="kd">get</span><span class="p">());</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h3 id="静态私有变量">静态私有变量</h3>
<p>上面的私有变量在每次实例化对象的时候都会重新初始化,通过块级作用域(私有作用域)中定义私有变量或函数,同样可以创建对外公共的特权方法。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">age</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span><span class="c1">//静态私有变量</span>
<span class="kd">function</span> <span class="nx">run</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Box</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{};</span> <span class="c1">//构造方法,没有使用var,全局函数</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">go</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="c1">//原型方法</span>
<span class="k">return</span> <span class="nx">age</span> <span class="o">+</span> <span class="nx">run</span><span class="p">();</span>
<span class="p">};</span>
<span class="p">})();</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">go</span><span class="p">());</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="模块模式">模块模式</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="c1">//box是一个模块</span>
<span class="kd">var</span> <span class="nx">age</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">run</span><span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span> <span class="c1">//直接返回对象</span>
<span class="na">go</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">age</span> <span class="o">+</span> <span class="nx">run</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="p">}();</span>
<span class="nt"></script></span>
</code></pre></div></div>
javascript笔记--(第十五章)(二)函数与对象深入了解
2017-06-28T03:06:29+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第十五章)(二)函数与对象深入了解
<h2 id="prototype">prototype</h2>
<p>每一个函数对象都有一个显示的prototype属性,它代表了函数对象的原型(Function.prototype函数对象是个例外,没有prototype属性,)。</p>
<h2 id="proto"><strong>proto</strong></h2>
<p>每个普通对象都有一个名为__proto__的内部隐藏属性,指向于它所对应的构造函数的原型对象(chrome、firefox中名称为__proto__,并且可以被访问到)。原型链正是基于__proto__才得以形成(note:不是基于函数对象的属性prototype)。</p>
<p>所有构造器/函数对象(包括自定义的)都是由Function构造的,所以其__proto__都指向Function.prototype,它是一个空函数(Empty function)。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Number</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Boolean</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">String</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Array</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">RegExp</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Error</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Date</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// true </span>
<span class="kd">var</span> <span class="nx">Employee</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">(){</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">Person</span><span class="p">(){</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Employee</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Person</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//true </span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>JavaScript中有内置(build-in)构造器/对象共计12个(ES5中新加了JSON),这里列举了可访问的8个构造器。剩下如Global不能直接访问,Arguments仅在函数调用时由JS引擎创建,Math,JSON是以对象形式存在的,无需new。它们的__proto__是Object.prototype。如下:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Math</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">JSON</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Math</span> <span class="k">instanceof</span> <span class="nb">Object</span><span class="p">);</span><span class="c1">//true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Math</span> <span class="k">instanceof</span> <span class="nb">Function</span><span class="p">);</span><span class="c1">//false</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Array</span> <span class="k">instanceof</span> <span class="nb">Object</span><span class="p">);</span><span class="c1">//true </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Array</span> <span class="k">instanceof</span> <span class="nb">Function</span><span class="p">);</span><span class="c1">//true </span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>由以上测试得出,所有的构造器都来自于Function.prototype,甚至包括根构造器Object及Function自身。所有构造器都继承了Function.prototype的属性及方法。如length、call、apply、bind(ES5)。另,Function.prototype也是唯一一个typeof XXX.prototype为 “function”的prototype。其它的构造器的prototype都是一个普通对象,下面来测试下:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// function </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">Number</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">Boolean</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">String</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">Array</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">RegExp</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">Error</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">Date</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">)</span> <span class="c1">// object </span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>所有普通对象的__proto__都指向其构造器的prototype</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Foo</span><span class="p">(){</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">foo</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Foo</span><span class="p">();</span><span class="c1">//对象实例化 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">foo</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nx">Foo</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//true</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">__proto__</span> <span class="o">===</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//true</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="constuctor">constuctor</h2>
<p>每个函数对象都有名为“prototype”的属性(上面提到过Function.prototype函数对象是个例外,没有prototype属性),用于引用原型对象。此原型对象又有名为“constructor”的属性,它反过来引用函数本身。这是一种循环引用。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">arr</span> <span class="o">=</span> <span class="p">[</span><span class="dl">"</span><span class="s2">aaa</span><span class="dl">"</span><span class="p">,</span> <span class="dl">"</span><span class="s2">bbb</span><span class="dl">"</span><span class="p">],</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arr</span><span class="p">.</span><span class="kd">constructor</span> <span class="o">===</span> <span class="nb">Array</span><span class="p">);</span><span class="c1">//true </span>
<span class="kd">function</span> <span class="nx">Foo</span><span class="p">(){</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Foo</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="kd">constructor</span> <span class="o">===</span> <span class="nx">Foo</span><span class="p">);</span><span class="c1">//true </span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>Function、Object、Prototype、__proto__内存关系图</p>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十五章)(二)函数与对象深入了解-1.png" alt="" /></p>
<p>堆区图说明:
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十五章)(二)函数与对象深入了解-2.png" alt="" /></p>
<p>Function.prototype函数对象图内部表示prototype属性的红色虚框,只是为了说明这个属性不存在。</p>
<p>通过上面这张图可以得出以下几点:</p>
<ul>
<li>所有对象,包括函数对象的原型链最终都指向了Object.prototype,而Object.prototype.<strong>proto</strong>===null,原型链至此结束。</li>
<li>Animal.prototype是一个普通对象。</li>
<li>Object是一个函数对象,也是Function构造的,Object.prototype是一个普通对象。</li>
<li>Object.prototype.__proto__指向null。</li>
<li>Function.prototype是一个函数对象,前面说函数对象都有一个显示的prototype属性,但是Function.prototype却没有prototype属性, Function.prototype.prototype===undefined,所以Function.prototype函数对象是一个特例,没有prototype属性。</li>
</ul>
<h2 id="函数与对象的关系">函数与对象的关系</h2>
<p>通过上图我们可以推测出js内部实现的一些原理和引擎初始化执行顺序:</p>
<ul>
<li>(1)创建一个Object.prototype对象,所有的对象(包括函数对象)都将继承这个对象的属性和方法,Object.prototype用来定义所有对象将继承的属性和方法;</li>
<li>(2)创建一个Function.prototype函数对象,所有的函数都将继承这个对象的属性和方法,Function.prototype这个特殊的函数对象主要用来给函数对象定义一些系统内置的函数和属性,如apply,call,length,arguments等。;</li>
<li>(3)将Function.prototype的__proto__属性指向Object.prototype,使其继承Object.prototype的属性和方法;</li>
<li>(4)创建Function对象,将其__proto__属性和protoype属性都指向Function.prototype;</li>
<li>(5)用Function对象构造其他本地构造器(Object Function Array String Boolean Number Date RegExp Error EvalError RangeError ReferenceError SyntaxError TypeError URIError),这些本地构造器的__proto__都将指向其对应的构造器(Function)的原型对象(Function.prototype)。需要注意的是,在构造Object构造器的时候会将Object.prototype挂载在其prototype属性上,所有构造器的原型对象的__proto__默认是指向Object.prototype的;</li>
<li>(5)客户端使用本地构造器构造js中的一切本地对象,也可以用Function对象(隐式function)构造自定义构造器;</li>
</ul>
<p>通过上面的一些推理,我们可以理解为,js原型链的源头其实是Object.prototype。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Number</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span> <span class="k">instanceof</span> <span class="nb">Object</span><span class="p">);</span><span class="c1">//true</span>
<span class="o"><</span><span class="nx">script</span> <span class="nx">type</span><span class="o">=</span><span class="dl">"</span><span class="s2">text/javascript</span><span class="dl">"</span><span class="o">></span>
</code></pre></div></div>
<p>(注意:对象只是js中的一种概念,不要和Object构造器混肴,instanceof操作符只是按照ECMASCript标准返回布尔值,这里并不能说明a对象和Object.prototype有直接关系,只不过其原型链最终指向了Object.portotype)</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//function(){},空函数</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="kd">constructor</span><span class="p">);</span><span class="c1">//function Function(){ [native code] },Function构造器</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//Object{}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//Object{}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="kd">constructor</span><span class="p">);</span><span class="kd">function</span> <span class="nx">Obeject</span><span class="p">(){}</span><span class="err">,</span><span class="nx">Object构造器</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//null</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="普通对象的创建过程">普通对象的创建过程</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Foo</span><span class="p">(</span><span class="nx">num</span><span class="p">){};</span>
<span class="kd">var</span> <span class="nx">foo</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Foo</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>当执行new Foo(1)时:</p>
<ul>
<li>(1)javascript引擎在内存中开辟一块新的内存,一个新对象被创建。修改新对象的__proto__,指向Foo.prototype,它继承自Foo.prototype;</li>
<li>(2)构造函数 Foo 被执行。执行的时候,相应的传参会被传入,同时上下文(this)会被指定为这个新实例。new Foo 等同于 new Foo(), 只能用在不传递任何参数的情况;</li>
<li>(3)如果构造函数返回了一个“对象”,那么这个对象会取代整个new出来的结果。如果构造函数没有返回对象,那么new出来的结果为步骤1创建的对象。</li>
</ul>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Foo1</span><span class="p">(</span><span class="nx">num</span><span class="p">){</span>
<span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">foo1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Foo1</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">foo1</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="nx">Foo1</span><span class="p">{}</span>
<span class="kd">function</span> <span class="nx">Foo2</span><span class="p">(){</span>
<span class="k">return</span> <span class="p">{};</span><span class="c1">//返回对象,会覆盖new出来的对象</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">foo2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Foo2</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">foo2</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//Object{}</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="instaceof操作符">instaceof操作符</h2>
<p><em>语法</em></p>
<p>object instanceof constructor</p>
<p><em>描述</em></p>
<p>instanceof 运算符用来检测 constructor.prototype 是否存在于参数 object 的原型链上,constructor必须是一个构造器,否则将报错。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//function(){}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//function(){}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//Object对象</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">-----------------------</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//function(){}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span><span class="c1">//Object对象</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//null</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">__proto__</span><span class="o">==</span><span class="nb">Object</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">==</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span> <span class="k">instanceof</span> <span class="nb">Object</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">==</span> <span class="nb">Object</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Object</span> <span class="k">instanceof</span> <span class="nb">Function</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">==</span> <span class="nb">Function</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Function</span> <span class="k">instanceof</span> <span class="nb">Function</span><span class="p">);</span><span class="c1">//true</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>instanceof操作符和对象的isPrototypeOf方法功能一样,只不过isPrototypeOf的调用者可以是一个对象也可以是一个构造器。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="kd">function</span> <span class="nx">B</span><span class="p">(){};</span>
<span class="nx">B</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nx">a</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">B</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">isPrototypeOf</span><span class="p">(</span><span class="nx">b</span><span class="p">));</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span> <span class="k">instanceof</span> <span class="nx">a</span><span class="p">);</span><span class="c1">//报错</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>参考:</p>
<p><a href="http://blog.csdn.net/cuew1987/article/details/15498121">http://blog.csdn.net/cuew1987/article/details/15498121</a></p>
<p><a href="http://www.blogjava.net/heavensay/archive/2013/10/20/405440.html">http://www.blogjava.net/heavensay/archive/2013/10/20/405440.html</a></p>
javascript笔记--(第十五章)(一)面向对象与原型
2017-06-28T02:29:56+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/28/javascript笔记--(第十五章)(一)面向对象与原型
<h2 id="面向对象">面向对象</h2>
<p>ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP)。面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性和方法的对象。但是,ECMAScript没有类的概念,因此它的对象也与基于类的语言中的对象有所不同。</p>
<h2 id="工厂方法">工厂方法</h2>
<p>解决实例化对象产生大量重复的问题</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">createObject</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//集中实例化的函数</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">obj</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box1</span> <span class="o">=</span> <span class="nx">createObject</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span> <span class="c1">//第一个实例</span>
<span class="kd">var</span> <span class="nx">box2</span> <span class="o">=</span> <span class="nx">createObject</span><span class="p">(</span><span class="dl">'</span><span class="s1">Jack</span><span class="dl">'</span><span class="p">,</span> <span class="mi">200</span><span class="p">);</span> <span class="c1">//第二个实例</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box1</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box2</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="构造函数">构造函数</h2>
<p>解决了重复实例化的问题,又解决了对象识别的问题</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//构造函数模式</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span> <span class="c1">//new Box()即可</span>
<span class="kd">var</span> <span class="nx">box2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">(</span><span class="dl">'</span><span class="s1">Jack</span><span class="dl">'</span><span class="p">,</span> <span class="mi">200</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box1</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box1</span> <span class="k">instanceof</span> <span class="nx">Box</span><span class="p">);</span> <span class="c1">//很清晰的识别他从属于Box </span>
<span class="nt"></script></span>
</code></pre></div></div>
<p><em>构造函数的方法有一些规范:</em></p>
<ul>
<li>函数名和实例化构造名相同且大写,(PS:非强制,但这么写有助于区分构造函数和普通函数);</li>
<li>通过构造函数创建对象,必须使用new运算符。</li>
</ul>
<p><em>构造函数实例化对象过程:</em></p>
<ul>
<li>(1)当使用了构造函数,并且new 构造函数(),那么就后台执行了new Object();</li>
<li>(2)将构造函数的作用域给新对象,(即new Object()创建出的对象),而函数体内的this就代表new Object()出来的对象。</li>
<li>(3)执行构造函数内的代码;</li>
<li>(4)返回新对象(后台直接返回)。</li>
</ul>
<p>构造函数和普通函数的唯一区别,就是他们调用的方式不同。只不过,构造函数也是函数,必须用new运算符来调用,否则就是普通函数。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span> <span class="c1">//构造模式调用</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span>
<span class="nx">Box</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="mi">20</span><span class="p">);</span> <span class="c1">//普通模式调用,无效</span>
<span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="nx">o</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Jack</span><span class="dl">'</span><span class="p">,</span> <span class="mi">200</span><span class="p">)</span> <span class="c1">//对象冒充调用</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">o</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span>
</code></pre></div></div>
<p>函数属性引用问题:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span> <span class="c1">//传递一致</span>
<span class="kd">var</span> <span class="nx">box2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span> <span class="c1">//同上</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box1</span><span class="p">.</span><span class="nx">name</span> <span class="o">==</span> <span class="nx">box2</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span> <span class="c1">//true,属性的值相等</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box1</span><span class="p">.</span><span class="nx">run</span> <span class="o">==</span> <span class="nx">box2</span><span class="p">.</span><span class="nx">run</span><span class="p">);</span> <span class="c1">//false,方法其实也是一种引用地址</span>
</code></pre></div></div>
<p>为了解决函数引用地址不一致的问题,可以使用外部函数:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">Box</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="nx">run</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">run</span><span class="p">()</span> <span class="p">{</span> <span class="c1">//通过外面调用,保证引用地址一致</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>虽然使用了全局的函数run()来解决了保证引用地址一致的问题,但这种方式又带来了一个新的问题,全局中的this在对象调用的时候是Box本身,而当作普通函数调用的时候,this又代表window。</p>
<h2 id="原型">原型</h2>
<p>我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法,逻辑上可以这么理解:prototype是通过调用构造函数而创建的原型对象。简单的说就是静态属性和方法。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">()</span> <span class="p">{};</span><span class="c1">//声明一个构造函数</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">;</span><span class="c1">//在原型里添加属性</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span><span class="c1">//在原型里添加方法</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">实例化之前:</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">box1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">实例化之后:</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">==</span> <span class="nx">box1</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span> <span class="c1">//true,证明Box的原型对象在实例化之前就已经存在</span>
<span class="kd">var</span> <span class="nx">box2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box1</span><span class="p">.</span><span class="nx">run</span> <span class="o">==</span> <span class="nx">box2</span><span class="p">.</span><span class="nx">run</span><span class="p">);</span><span class="c1">//true,方法的引用地址保持一致 </span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>运行结果:
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十五章)(一)面向对象与原型-1.jpg" alt="null" /></p>
<p>原型对象中的constructor是一个函数,代表构造函数本身</p>
<p>为了更进一步了解构造函数的声明方式和原型模式的声明方式,我们通过图示来了解一下:</p>
<p>构造函数模式:
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十五章)(一)面向对象与原型-2.jpg" alt="" /></p>
<p>原型模式:
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十五章)(一)面向对象与原型-3.jpg" alt="" /></p>
<p>在原型模式声明中,多了两个属性,这两个属性都是创建对象时自动生成的。__proto__属性是实例指向原型对象的一个指针。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">()</span> <span class="p">{}</span> <span class="c1">//声明一个构造函数</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">;</span> <span class="c1">//在原型里添加属性</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span> <span class="c1">//在原型里添加方法</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>在浏览器里查看打印的结果:
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十五章)(一)面向对象与原型-4.jpg" alt="" /></p>
<p>可以看到,Box实例对象的__proto__属性指向的Box构造函数的原型对象,原型对象里的constructor是原型本身,Box构造函数的原型对象默认是继承自Object。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">()</span> <span class="p">{}</span> <span class="c1">//声明一个构造函数</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Number</span><span class="p">(</span><span class="mi">2</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Number</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>查看输出结果:
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十五章)(一)面向对象与原型-5.jpg" alt="" /></p>
<p>从结果可以看出,Number的原型对象重写了toString和valueOf方法,原型对象继承自Object</p>
<p>判断一个对象是否在一个对象的原型链上,可以使用isPrototypeOf()方法来测试。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">isPrototypeOf</span><span class="p">(</span><span class="nx">box</span><span class="p">));</span>
</code></pre></div></div>
<p>对象属性和方法的访问顺序:</p>
<ol>
<li>先查找构造函数实例里的属性或方法,如果有,立刻返回;</li>
<li>如果构造函数实例里没有,则去它的原型对象里找,如果有,就返回;</li>
</ol>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">()</span> <span class="p">{};</span><span class="c1">//声明一个构造函数</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">;</span><span class="c1">//在原型里添加属性</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">box</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">li</span><span class="dl">"</span><span class="p">;</span><span class="c1">//li</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span><span class="c1">//覆盖原型中的属性</span>
<span class="k">delete</span> <span class="nx">box</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span><span class="c1">//删除构造函数里的属性</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span><span class="c1">//Lee </span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>hasOwnProperty():判断对象实例中是否有某个属性(不包括原型链)。</p>
<p>in操作符:属性是否存在于实例或者原型中。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">lisong</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">26</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">isProperty</span><span class="p">(</span><span class="nx">object</span><span class="p">,</span> <span class="nx">property</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//判断原型中是否存在属性</span>
<span class="k">return</span> <span class="o">!</span><span class="nx">object</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="nx">property</span><span class="p">)</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">property</span> <span class="k">in</span> <span class="nx">object</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">isProperty</span><span class="p">(</span><span class="nx">box</span><span class="p">,</span> <span class="dl">'</span><span class="s1">name</span><span class="dl">'</span><span class="p">))</span> <span class="c1">//false</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">isProperty</span><span class="p">(</span><span class="nx">box</span><span class="p">,</span> <span class="dl">'</span><span class="s1">age</span><span class="dl">'</span><span class="p">))</span> <span class="c1">//true</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>使用字面量创建原型对象:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">(){}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">age</span><span class="p">:</span><span class="mi">26</span><span class="p">,</span>
<span class="na">name</span><span class="p">:</span><span class="dl">"</span><span class="s2">lisong</span><span class="dl">"</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span><span class="c1">//lisong</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="kd">constructor</span> <span class="o">==</span> <span class="nx">Box</span><span class="p">);</span><span class="c1">//false</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="kd">constructor</span> <span class="o">==</span> <span class="nb">Object</span><span class="p">);</span><span class="c1">//true</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>运行结果:
<img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-28-javascript笔记--(第十五章)(一)面向对象与原型-6.jpg" alt="" /></p>
<p>从结果可以看出,用字面量创建的原型对象,其constructor属性会指向Object的构造函数,而不会指向Box的构造函数</p>
<h2 id="组合构造函数原型模式">组合构造函数+原型模式</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">Box</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//不共享的使用构造函数</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span> <span class="nx">family</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">父亲</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">母亲</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">妹妹</span><span class="dl">'</span><span class="p">];</span>
<span class="p">};</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span> <span class="c1">//共享的使用原型模式</span>
<span class="na">constructor</span> <span class="p">:</span> <span class="nx">Box</span><span class="p">,</span>
<span class="na">run</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">family</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
</code></pre></div></div>
<p>这种混合模式很好的解决了传参和引用共享的大难题。是创建对象比较好的方法</p>
<h2 id="动态原型模式">动态原型模式</h2>
<p>原型模式,不管你是否创建了对象实例,它都会初始化原型中的方法,并且在声明一个对象时,构造函数+原型部分让人感觉又很怪异,最好就是把构造函数和原型封装到一起。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">Box</span><span class="p">(</span><span class="nx">name</span> <span class="p">,</span><span class="nx">age</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//将所有信息封装到函数体内</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="k">typeof</span> <span class="k">this</span><span class="p">.</span><span class="nx">run</span> <span class="o">!=</span> <span class="dl">'</span><span class="s1">function</span><span class="dl">'</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//仅在第一次调用的初始化</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">};</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span>
</code></pre></div></div>
<h2 id="寄生构造函数">寄生构造函数</h2>
<p>寄生构造函数,其实就是工厂模式+构造函数模式。这种模式比较通用,但不能instanceof确定对象关系(可以认为使用new构建的对象如果没有用构造函数return的方式来返回对象,那么new出来的对象会带有某种标记或属性用来给instanceof操作符确定对象关系)。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">Box</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">运行中...</span><span class="dl">'</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">obj</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>假设要创建一个具有额外方法的引用类型。由于之前说明不建议直接String.prototype.addstring,可以通过寄生构造的方式添加。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">myString</span><span class="p">(</span><span class="nx">string</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">String</span><span class="p">(</span><span class="nx">string</span><span class="p">);</span>
<span class="nx">str</span><span class="p">.</span><span class="nx">addstring</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span> <span class="o">+</span> <span class="dl">'</span><span class="s1">,被添加了!</span><span class="dl">'</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">str</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">myString</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">);</span> <span class="c1">//比直接在引用原型添加要繁琐好多</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">addstring</span><span class="p">());</span>
</code></pre></div></div>
<h2 id="原型链继承">原型链继承</h2>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">()</span> <span class="p">{</span> <span class="c1">//Box构造</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">Desk</span><span class="p">()</span> <span class="p">{</span> <span class="c1">//Desk构造</span>
<span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Desk</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span> <span class="c1">//Desc继承了Box,通过原型,形成链条</span>
<span class="kd">var</span> <span class="nx">desk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Desk</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">desk</span><span class="p">.</span><span class="nx">age</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">desk</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
<span class="c1">//得到被继承的属性</span>
<span class="kd">function</span> <span class="nx">Table</span><span class="p">()</span> <span class="p">{</span> <span class="c1">//Table构造</span>
<span class="k">this</span><span class="p">.</span><span class="nx">level</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">AAAAA</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Table</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Desk</span><span class="p">();</span> <span class="c1">//继续原型链继承</span>
<span class="kd">var</span> <span class="nx">table</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Table</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">table</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span> <span class="c1">//继承了Box和Desk</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">table</span> <span class="k">instanceof</span> <span class="nb">Object</span><span class="p">);</span> <span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">desk</span> <span class="k">instanceof</span> <span class="nx">Table</span><span class="p">);</span> <span class="c1">//false,desk是table的超类</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">table</span> <span class="k">instanceof</span> <span class="nx">Desk</span><span class="p">);</span> <span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">table</span> <span class="k">instanceof</span> <span class="nx">Box</span><span class="p">);</span> <span class="c1">//true</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="对象冒充继承借用构造函数">对象冒充继承(借用构造函数)</h2>
<p>对象冒充继承主要解决超类型无法传参的问题</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">(</span><span class="nx">age</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Jack</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Hello</span><span class="dl">'</span><span class="p">]</span>
<span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">Desk</span><span class="p">(</span><span class="nx">age</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">age</span><span class="p">);</span><span class="c1">//对象冒充,给超类型传参</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">desk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Desk</span><span class="p">(</span><span class="mi">200</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">desk</span><span class="p">.</span><span class="nx">age</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">desk</span><span class="p">.</span><span class="nx">name</span><span class="p">);</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="组合继承原型链对象冒充">组合继承(原型链+对象冒充)</h2>
<p>借用构造函数虽然解决了刚才两种问题,但没有原型,复用则无从谈起。所以,我们需要原型链+借用构造函数的模式,这种模式成为组合继承。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">(</span><span class="nx">age</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Jack</span><span class="dl">'</span><span class="p">,</span> <span class="dl">'</span><span class="s1">Hello</span><span class="dl">'</span><span class="p">]</span>
<span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">+</span> <span class="k">this</span><span class="p">.</span><span class="nx">age</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">Desk</span><span class="p">(</span><span class="nx">age</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">age</span><span class="p">);</span><span class="c1">//对象冒充,主要用来继承Box构造函数里的属性,第二次调用超类Box</span>
<span class="p">}</span>
<span class="nx">Desk</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Box</span><span class="p">();</span><span class="c1">//原型链继承,用来继承父对象,会包括父对象的实例属性和父对象原型链的属性,第一次调用超类Box</span>
<span class="kd">var</span> <span class="nx">desk</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Desk</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">desk</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span>
<span class="kd">function</span> <span class="nx">isPropertyToProto</span><span class="p">(</span><span class="nx">object</span><span class="p">,</span> <span class="nx">property</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//判断原型中是否存在属性</span>
<span class="k">return</span> <span class="o">!</span><span class="nx">object</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="nx">property</span><span class="p">)</span> <span class="o">&&</span> <span class="p">(</span><span class="nx">property</span> <span class="k">in</span> <span class="nx">object</span><span class="p">);</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">isPropertyToProto</span><span class="p">(</span><span class="nx">desk</span><span class="p">,</span><span class="dl">"</span><span class="s2">run</span><span class="dl">"</span><span class="p">));</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">desk</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="dl">"</span><span class="s2">age</span><span class="dl">"</span><span class="p">));</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">desk</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">.</span><span class="nx">hasOwnProperty</span><span class="p">(</span><span class="dl">"</span><span class="s2">age</span><span class="dl">"</span><span class="p">));</span><span class="c1">//true</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>组合继承缺点:某些属性在构造函数里和原型对象里都有,重复了,还有就是超类被调用了两次</p>
<h2 id="原型式继承">原型式继承</h2>
<p>借助原型并基于已有的对象创建新对象,同时还不必因此创建自定义类型。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">obj</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//传递一个字面量函数</span>
<span class="kd">function</span> <span class="nx">F</span><span class="p">()</span> <span class="p">{}</span> <span class="c1">//创建一个构造函数</span>
<span class="nx">F</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nx">o</span><span class="p">;</span> <span class="c1">//把字面量函数赋值给构造函数的原型</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">F</span><span class="p">();</span> <span class="c1">//最终返回出实例化的构造函数</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="p">{</span> <span class="c1">//字面量对象</span>
<span class="na">name</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span>
<span class="na">arr</span> <span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">哥哥</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">妹妹</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">姐姐</span><span class="dl">'</span><span class="p">]</span>
<span class="p">};</span>
<span class="kd">var</span> <span class="nx">box1</span> <span class="o">=</span> <span class="nx">obj</span><span class="p">(</span><span class="nx">box</span><span class="p">);</span> <span class="c1">//传递</span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="寄生式继承原型式工厂模式">寄生式继承(原型式+工厂模式)</h2>
<p>原型式+工厂模式结合而来,目的是为了在原型式的基础上封装创建对象的过程。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">obj</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//传递一个字面量函数</span>
<span class="kd">function</span> <span class="nx">F</span><span class="p">()</span> <span class="p">{}</span> <span class="c1">//创建一个构造函数</span>
<span class="nx">F</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nx">o</span><span class="p">;</span> <span class="c1">//把字面量函数赋值给构造函数的原型</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">F</span><span class="p">();</span> <span class="c1">//最终返回出实例化的构造函数</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="p">{</span> <span class="c1">//字面量对象</span>
<span class="na">name</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">,</span>
<span class="na">arr</span> <span class="p">:</span> <span class="p">[</span><span class="dl">'</span><span class="s1">哥哥</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">妹妹</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">姐姐</span><span class="dl">'</span><span class="p">]</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">create</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="p">{</span> <span class="c1">//封装创建过程</span>
<span class="kd">var</span> <span class="nx">f</span><span class="o">=</span> <span class="nx">obj</span><span class="p">(</span><span class="nx">o</span><span class="p">);</span>
<span class="nx">f</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">arr</span><span class="p">;</span> <span class="c1">//同样,会共享引用</span>
<span class="p">};</span>
<span class="k">return</span> <span class="nx">f</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">box1</span> <span class="o">=</span> <span class="nx">create</span><span class="p">(</span><span class="nx">box</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box1</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span><span class="c1">//["哥哥", "妹妹", "姐姐"]</span>
<span class="nt"></script></span>
</code></pre></div></div>
<p>上面的代码主要是为了封装额外的方法和属性</p>
<h2 id="寄生组合继承寄生组合">寄生组合继承(寄生+组合)</h2>
<p>解决组合继承超类调用两次的问题</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">Box</span><span class="p">(</span><span class="nx">name</span><span class="p">)</span> <span class="p">{</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">arr</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">哥哥</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">妹妹</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">父母</span><span class="dl">'</span><span class="p">];</span>
<span class="p">}</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">run</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="k">this</span><span class="p">.</span><span class="nx">name</span><span class="p">;</span>
<span class="p">};</span>
<span class="kd">function</span> <span class="nx">Desk</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span> <span class="nx">age</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">Box</span><span class="p">.</span><span class="nx">call</span><span class="p">(</span><span class="k">this</span><span class="p">,</span> <span class="nx">name</span><span class="p">);</span><span class="c1">//对象冒充 </span>
<span class="k">this</span><span class="p">.</span><span class="nx">age</span> <span class="o">=</span> <span class="nx">age</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">obj</span><span class="p">(</span><span class="nx">o</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">function</span> <span class="nx">F</span><span class="p">()</span> <span class="p">{}</span>
<span class="nx">F</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nx">o</span><span class="p">;</span>
<span class="k">return</span> <span class="k">new</span> <span class="nx">F</span><span class="p">();</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">create</span><span class="p">(</span><span class="nx">box</span><span class="p">,</span> <span class="nx">desk</span><span class="p">)</span> <span class="p">{</span><span class="c1">//寄生式继承 </span>
<span class="kd">var</span> <span class="nx">f</span> <span class="o">=</span> <span class="nx">obj</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">prototype</span><span class="p">);</span>
<span class="nx">f</span><span class="p">.</span><span class="kd">constructor</span> <span class="o">=</span> <span class="nx">desk</span><span class="p">;</span>
<span class="nx">desk</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="nx">f</span><span class="p">;</span>
<span class="cm">/*
desk.prototype = box.prototype;
desk.prototype.constructor = desk;//会同时修改掉box的constructor,所以不能使用desk.prototype = box.prototype
*/</span>
<span class="p">}</span>
<span class="nx">create</span><span class="p">(</span><span class="nx">Box</span><span class="p">,</span><span class="nx">Desk</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Desk</span><span class="p">(</span><span class="dl">"</span><span class="s2">lisong</span><span class="dl">"</span><span class="p">,</span><span class="mi">26</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">d</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span><span class="c1">//lisong </span>
<span class="nt"></script></span>
</code></pre></div></div>
<h2 id="极晚绑定very-late-binding">极晚绑定(Very Late Binding)</h2>
<p>从技术上讲,根本不存在极晚绑定。该术语描述 ECMAScript 中的一种现象,即能够在对象实例化后再定义它的原型链的方法。例如:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">o</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
<span class="nb">Object</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">sayHi</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="dl">"</span><span class="s2">hi</span><span class="dl">"</span><span class="p">);</span>
<span class="p">};</span>
<span class="nx">o</span><span class="p">.</span><span class="nx">sayHi</span><span class="p">();</span><span class="c1">//hi</span>
</code></pre></div></div>
<p>需要注意的是,这种情况下对原型链是有影响的。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">F</span><span class="p">(){};</span>
<span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">F</span><span class="p">();</span>
<span class="nx">F</span><span class="p">.</span><span class="nx">prototype</span> <span class="o">=</span> <span class="p">{</span><span class="na">a</span><span class="p">:</span><span class="mi">1</span><span class="p">};</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">F</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//F {}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">.</span><span class="nx">__proto__</span><span class="p">);</span><span class="c1">//{a: 1}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">a</span><span class="p">);</span> <span class="c1">//undefined</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">.</span><span class="nx">a</span><span class="p">);</span> <span class="c1">//1</span>
</code></pre></div></div>
javascript笔记--(第十四章)内置对象
2017-06-27T10:26:31+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第十四章)内置对象
<h2 id="内置对象">内置对象</h2>
<p>ECMA-262对内置对象的定义是:“由ECMAScript实现提供的、不依赖宿主环境的对象,这些对象在ECMAScript程序执行之前就已经存在了。”意思就是说,开发人员不必显示地实例化内置对象;因为它们已经实例化了。ECMA-262只定义了两个内置对象:Global和Math。</p>
<h3 id="global">Global</h3>
<p>Global(全局)对象是ECMAScript中一个特别的对象,因为这个对象是不存在的。在ECMAScript中不属于任何其他对象的属性和方法,都属于它的属性和方法。所以,事实上,并不存在全局变量和全局函数;所有在全局作用域定义的变量和函数,都是Global对象的属性和方法。Web浏览器将Global作为window对象的一部分加以实现。</p>
<h3 id="uri编码方法">URI编码方法</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var str = "http://www.baidu.com/李";
var en1 = encodeURI(str);
console.log(en1);//http://www.baidu.com/%E6%9D%8E
console.log(decodeURI(en1));//http://www.baidu.com/李
var en2 = encodeURIComponent(str);
console.log(en2);//http%3A%2F%2Fwww.baidu.com%2F%E6%9D%8E
console.log(decodeURIComponent(en2));//http://www.baidu.com/李
var en3 = escape(str);
console.log(en3);//http%3A//www.baidu.com/%u674E
console.log(unescape(en3));//http://www.baidu.com/李
</script>
</code></pre></div></div>
<p>注意:
URI方法如上所述的四种,用于代替已经被ECMA-262第3版废弃的escape()和unescape()方法。URI方法能够编码所有的Unicode字符,而原来的只能正确地编码ASCII字符。所以建议不要再使用escape()和unescape()方法;</p>
<p>escape、unescape函数采用ISO Latin字符集对指定字符串进行编码。所有的空格符、标点符号、特殊字符以及其他非ASCII字符都将被转化成%xx格式的字符编码(xx等于该字符在字符集表里面的编码的16进制数字);</p>
<p>encodeURI、decodeURI将指定字符串采用UTF-8编码格式转化成escape格式的字符串(或把escape格式的字符串转化为UTF-8编码)。不会被此方法编码的字符有:! @ # $& * ( ) = : / ; ? + ‘;</p>
<p>encodeURIComponent函数把URI字符串采用UTF-8编码格式转化成escape格式的字符串。与encodeURI()相比,这个方法将对更多的字符进行编码;</p>
<p>encodeURIComponent()主要用来编码url某个部件,列入参数中含有#等特殊符号。encodeURI()主要用来对整个url编码,列入参数含有中文。</p>
<h3 id="eval方法">eval()方法</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
eval("var name='lisong'");
console.log(name);//lisong
eval('function test() {return 123}');
console.log(test());//123
</script>
</code></pre></div></div>
<h3 id="global对象属性">Global对象属性</h3>
<p>Global对象包含了一些属性:undefined、NaN、Object、Array、Function等等。</p>
<h3 id="math对象">Math对象</h3>
<p>min()和max()方法</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
console.log(Math.min(5,3,4,2,1));//1
console.log(Math.max(5,3,4,2,1));//5
</script>
</code></pre></div></div>
<p><em>舍入方法</em></p>
<ul>
<li>Math.ceil():执行向上舍入,即它总是将数值向上舍入为最接近的整数</li>
<li>Math.floor():执行向下舍入,即它总是将数值向下舍入为最接近的整数</li>
<li>Math.round():执行标准舍入,即它总是将数值四舍五入为最接近的整数</li>
</ul>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
console.log(Math.ceil(5.1));//6
console.log(Math.ceil(-5.9));//-5
console.log(Math.floor(5.9));//5
console.log(Math.floor(-5.1));//-6
console.log(Math.round(5.9));//6
console.log(Math.round(-5.4));//-5
console.log(Math.round(-5.6));//-6
</script>
</code></pre></div></div>
<p><em>其他常用方法</em></p>
<ul>
<li>random():返回介于0到1之间一个随机数,不包括0和1。</li>
<li>Math.abs(num) :返回num的绝对值</li>
<li>Math.pow(num,power) :返回num的power次幂</li>
<li>Math.sqrt(num) :返回num的平方根</li>
</ul>
javascript笔记--(第十三章)基本包装类型
2017-06-27T10:10:10+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第十三章)基本包装类型
<h2 id="基本包装类型">基本包装类型</h2>
<p>为了便于操作基本类型值,ECMAScript提供了3个特殊的引用类型:Boolean、Number和String。这些类型与其他引用类型相似,但同时也具有与各自的基本类型相应的特殊行为。实际上,每当读取一个基本类型值的时候,后台就会创建一个对应的基本包装类型的对象,从而能够调用一些方法来操作这些数据。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var str = 'my name is lisong';
str.name = 'lisong';
console.log(str.name); //undefined,基本类型不可以设置属性
str = str.substring(3);//基本类型有固有的方法,系统预设的
console.log(str); //name is lisong
var str = new String('my name is lisong');
str.name = 'lisong';
console.log(str.name);//lisong,对象可以设置属性
str = str.substring(3);//返回的是字符串,不是String对象
str.name = 'lisong';
console.log(str.name);//undefined,返回的str是字符串,不能设置属性
</script>
</code></pre></div></div>
<p>基本包装类型的原理:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var a = '123';
console.log(a.length);//3
a.length = 2;
console.log(a.length);//3
</script>
</code></pre></div></div>
<p>每当我们使用基本类型的属性的时候,JS引擎内部将为我们隐式地创建一个包装对象,使用完后将会销毁。第三行试图更改a.length的值,但是其只是在这一行有效,当第四行在次读取的时候,第三行构造的引用已经销毁了,会重新构造一个引用类型(new String(a)),所以其读取length仍然是3。(真实实现并不一定是这样,但整个过程看起来是这样)</p>
<h3 id="boolean类型">Boolean类型</h3>
<p>Boolean类型没有特定的属性或者方法。</p>
<h3 id="number对象">Number对象</h3>
<p>Number 对象方法</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:155px; background-color:rgb(213,213,213)">
方法
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_tostring_number.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">toString</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
把数字转换为字符串,使用指定的基数。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_tolocalestring_number.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">toLocaleString</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
把数字转换为字符串,使用本地数字格式顺序。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_tofixed.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">toFixed</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
把数字转换为字符串,结果的小数点后有指定位数的数字。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_toexponential.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">toExponential</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
把对象的值转换为指数计数法。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_toprecision.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">toPrecision</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
把数字格式化为指定的长度。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_valueof_number.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">valueOf</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
返回一个 Number 对象的基本数字值。
</td>
</tr>
</tbody>
</table>
<p><em>toPrecision(num):</em></p>
<p>返回 NumberObject 的字符串表示,包含num 个有效数字。如果 num 足够大,能够包括 NumberObject 整数部分的所有数字,那么返回的字符串将采用定点计数法。否则,采用指数计数法,即小数点前有一位数字,小数点后有 num-1 位数字。必要时,该数字会被舍入或用 0 补足。</p>
<p><em>toFixed(num):</em></p>
<p>返回 NumberObject 的字符串表示,不采用指数计数法,小数点后有固定的 num 位数字。如果必要,该数字会被舍入,也可以用 0 补足,以便它达到指定的长度。如果 num 大于 le+21,则该方法只调用 NumberObject.toString(),返回采用指数计数法表示的字符串。</p>
<p><em>toExponential(num):</em></p>
<p>返回 NumberObject 的字符串表示,采用指数计数法,即小数点之前有一位数字,小数点之后有 num 位数字。该数字的小数部分将被舍入,必要时用 0 补足,以便它达到指定的长度。</p>
<p>以上三个函数一般只用到toFixed()。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mf">1000.789</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span> <span class="c1">//转换为字符串,传参可以转换进制 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toLocaleString</span><span class="p">());</span> <span class="c1">//本地形式,1,000.789 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toFixed</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span> <span class="c1">//小数点保留,1000.79 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toExponential</span><span class="p">());</span> <span class="c1">//指数形式,传参会保留小数点 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toPrecision</span><span class="p">(</span><span class="mi">3</span><span class="p">));</span> <span class="c1">//1.00e+3 </span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toPrecision</span><span class="p">(</span><span class="mi">4</span><span class="p">));</span> <span class="c1">//10001 </span>
</code></pre></div></div>
<h2 id="string对象常用方法">String对象常用方法:</h2>
<ul>
<li>indexOf(str, n) :从n开始搜索的第一个str,并将搜索的索引值返回</li>
<li>lastIndexOf(str, n) :从n开始搜索的最后一个str,并将搜索的索引值返回</li>
<li>concat(str1…str2) :将字符串参数串联到调用该方法的字符串</li>
<li>slice(n,m) :返回字符串n到m之间位置的字符串</li>
<li>substring(n,m): 同上</li>
<li>substr(n,m) :返回字符串n开始的m个字符串</li>
</ul>
<h3 id="slice与substring的区别">slice与substring的区别:</h3>
<ul>
<li>slice的start和end都可以为负数,substring的这两个参数为负数时将转换成0;</li>
<li>slice可以用于数组</li>
</ul>
javascript笔记--(第十二章)变量、作用域及内存
2017-06-27T09:50:14+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第十二章)变量、作用域及内存
<h2 id="基本类型和引用类型的存储">基本类型和引用类型的存储</h2>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-27-javascript笔记--(第十二章)变量、作用域及内存-1.jpg" alt="" /></p>
<h2 id="复制变量值">复制变量值</h2>
<p>基本类型和引用类型的变量复制是不一样的</p>
<h3 id="基本类型的变量复制">基本类型的变量复制:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = 'Lee'; //在栈内存生成一个box 'Lee'
var box2 = box; //在栈内存再生成一个box2 'Lee'
</script>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-27-javascript笔记--(第十二章)变量、作用域及内存-2.jpg" alt="" /></p>
<h3 id="引用类型的变量复制">引用类型的变量复制:</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = new Object(); //创建一个引用类型
box.name = 'Lee'; //新增一个属性
var box2 = box; //把引用地址赋值给box2
</script>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/JavaScript学习笔记/2017-06-27-javascript笔记--(第十二章)变量、作用域及内存-3.jpg" alt="" /></p>
<h2 id="检测类型">检测类型</h2>
<p>虽然typeof运算符在检查基本数据类型的时候非常好用,但检测引用类型的时候,它就不是那么好用了。通常,我们并不想知道它是不是对象,而是想知道它到底是什么类型的对象。因为数组也是object,null也是Object等等。这时我们可以采用instanceof运算符来查看。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = [1,2,3];
console.log(box instanceof Array); //true
console.log(box instanceof Object); //true
var box2 = {};
console.log(box2 instanceof Object); //true
var box3 = /g/;
console.log(box3 instanceof RegExp); //true
var box4 = new String('Lee');
console.log(box4 instanceof String); //true
var a = "lisong";
console.log(a instanceof String); //false
</script>
</code></pre></div></div>
<p>当使用instanceof检查基本类型的值时,它会返回false</p>
<h2 id="执行环境及作用域">执行环境及作用域</h2>
<p>全局执行环境是最外围的执行环境。在Web浏览器中,全局执行环境被认为是window对象。因此所有的全局变量和函数都是作为window对象的属性和方法创建的。</p>
<p>当执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁。如果是全局环境下,需要程序执行完毕,或者网页被关闭才会销毁。</p>
<p>每个执行环境都有一个与之关联的变量对象,就好比全局的window可以调用变量和属性一样。局部的环境也有一个类似window 的变量对象,环境中定义的所有变量和函数都保存在这个对象中。(我们无法访问这个变量对象,但解析器会处理数据时后台使用它)</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = 'blue';
function setBox() {
function setColor() {
var b = 'orange';
alert(box);
alert(b);
}
setColor(); //setColor()的执行环境在setBox()内
}
setBox();
</script>
</code></pre></div></div>
<p>每个函数被调用时都会创建自己的执行环境。当执行到这个函数时,函数的环境就会被推到环境栈中去执行,而执行后又在环境栈中弹出(退出),把控制权交给上一级的执行环境。</p>
<p>var关键字在函数里的区别:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">box</span><span class="p">(</span><span class="nx">num1</span><span class="p">,</span> <span class="nx">num2</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">sum</span> <span class="o">=</span> <span class="nx">num1</span> <span class="o">+</span> <span class="nx">num2</span><span class="p">;</span> <span class="c1">//如果去掉var就是全局变量了</span>
<span class="k">return</span> <span class="nx">sum</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span><span class="mi">10</span><span class="p">));</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">sum</span><span class="p">);</span> <span class="c1">//报错</span>
</code></pre></div></div>
<p>变量查询中,访问局部变量要比全局变量更快,因为不需要向上搜索作用域链,先搜索到的优先级高。</p>
<p>块级作用域表示诸如if语句等有花括号封闭的代码块。但是在js中是没有块级作用域的,即使for语句也不存在块级作用域。</p>
<h2 id="内存问题">内存问题</h2>
<p>JavaScript具有自动垃圾收集机制,也就是说,执行环境会负责管理代码执行过程中使用的内存。其他语言比如C和C++,必须手工跟踪内存使用情况,适时的释放,否则会造成很多问题。而JavaScript则不需要这样,它会自行管理内存分配及无用内存的回收。</p>
<p>JavaScript最常用的垃圾收集方式是标记清除。垃圾收集器会在运行的时候给存储在内存中的变量加上标记。然后,它会去掉环境中正在使用变量的标记,而没有被去掉标记的变量将被视为准备删除的变量。最后,垃圾收集器完成内存清理工作,销毁那些带标记的值并回收他们所占用的内存空间。</p>
<p>垃圾收集器是周期性运行的,这样会导致整个程序的性能问题。比如IE7以前的版本,它的垃圾收集器是根据内存分配量运行的,比如256个变量就开始运行垃圾收集器,这样,就不得不频繁地运行,从而降低的性能。</p>
<p>一般来说,确保占用最少的内存可以让页面获得更好的性能。那么优化内存的最佳方案,就是一旦数据不再有用,那么将其设置为null来释放引用,这个做法叫做解除引用。这一做法适用于大多数全局变量和全局对象。</p>
javascript笔记--(第十一章)Function类型
2017-06-27T09:37:03+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第十一章)Function类型
<h2 id="function">Function</h2>
<p>在ECMAScript中,Function(函数)实际上是对象。每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法。由于函数是对象,因此函数名实际上也是一个指向函数对象的指针。</p>
<h3 id="函数的声明">函数的声明</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
function box(num1, num2) {
return num1+ num2;
}
var box= function(num1, num2) {
return num1 + num2;
};
var box= new Function('num1', 'num2' ,'return num1 + num2');//更加具体的说明了函数是对象,会导致解析两次代码,尽量少用
</script>
</code></pre></div></div>
<h3 id="函数内部属性">函数内部属性</h3>
<p>在函数内部,有两个特殊的对象:arguments和this。arguments是一个类数组对象,包含着传入函数中的所有参数,主要用途是保存函数参数。但这个对象还有一个名叫callee的属性,该属性是一个指针,指向拥有这个arguments对象的函数。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">box</span><span class="p">(</span><span class="nx">num</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">num</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">num</span> <span class="o">*</span> <span class="nx">arguments</span><span class="p">.</span><span class="nx">callee</span><span class="p">(</span><span class="nx">num</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span><span class="c1">//使用callee来执行自身,防止如果box函数名称改变时,需要改变内部递归函数的民称</span>
<span class="p">}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>函数内部另一个特殊对象是this,其行为与Java和C#中的this大致相似。换句话说,this引用的是函数据以执行操作的对象。PS:当在全局作用域中调用函数时,this对象引用的就是window。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var name = "person";
var man = {
name:"lisong",
sayName:function(){
console.log(this.name);
}
};
man.sayName();//lisong
</script>
</code></pre></div></div>
<h3 id="函数属性和方法">函数属性和方法</h3>
<p>ECMAScript中的函数是对象,因此函数也有属性和方法。每个函数都包含两个属性:length和prototype。其中,length属性表示函数希望接收的命名参数的个数。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
function box(name, age) {
alert(name + age);
}
console.log(box.length);//2
</script>
</code></pre></div></div>
<p>prototype是原型对象,其下有两个方法:apply()和call()。这两个方法的用途都在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var name = "person";
function sayName1(age,addr) {
console.log(name+":"+age+":"+addr);
}
sayName1(26,"耒阳");//person:26:耒阳
var box={
name:"lisong",
sayName2:function(age,addr){
sayName1.apply(this,[age,addr]);
}
}
box.sayName2(26,"耒阳");//person:26:耒阳
function sayName3(age,addr) {
console.log(this.name+":"+age+":"+addr);//this
}
sayName3(26,"耒阳");//person:26:耒阳
var box={
name:"lisong",
sayName4:function(age,addr){
sayName3.apply(this,[age,addr]);
}
}
box.sayName4(26,"耒阳");//lisong:26:耒阳
var box={
name:"lisong",
sayName5:function(age,addr){
sayName3.call(this,age,addr);//call与apply唯一的不同即传递参数的方式不同,apply传递的是数组
}
}
box.sayName5(26,"耒阳");//lisong:26:耒阳
</script>
</code></pre></div></div>
javascript笔记--(第十章)正则表达式
2017-06-27T09:30:41+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第十章)正则表达式
<h2 id="正则表达式">正则表达式</h2>
<p>正则表达式(regular expression)是一个描述字符模式的对象。ECMAScript的RegExp类表示正则表达式,而String和RegExp都定义了使用正则表达式进行强大的模式匹配和文本检索与替换的函数。</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:119px; background-color:rgb(213,213,213)">
修饰符
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_regexp_i.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">i</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
执行对大小写不敏感的匹配。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_regexp_g.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">g</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
m
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
执行多行匹配。
</td>
</tr>
</tbody>
</table>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var reg1 = new RegExp("lisong",'ig');
var reg2 = new RegExp("lisong");
var reg3 = /lisong/ig;
var reg4 = /lisong/;
</script>
</code></pre></div></div>
<h3 id="regexp-对象的方法">RegExp 对象的方法</h3>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:120px; background-color:rgb(213,213,213)">
方法
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:446px; background-color:rgb(213,213,213)">
描述
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:28px; background-color:rgb(213,213,213)">
FF
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:27px; background-color:rgb(213,213,213)">
IE
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_regexp_compile.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">compile</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
编译正则表达式。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_exec_regexp.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">exec</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
检索字符串中指定的值。返回找到的值,并确定其位置。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_test_regexp.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">test</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
检索字符串中指定的值。返回 true 或 false。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
</tbody>
</table>
<p><em>test方法:</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">reg</span> <span class="o">=</span> <span class="sr">/lisong/</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">test</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lison</span><span class="dl">"</span><span class="p">));</span><span class="c1">//false</span>
</code></pre></div></div>
<p><em>exec方法:</em></p>
<p>如果 exec() 找到了匹配的文本,则返回一个结果数组。否则,返回 null。此数组的第 0 个元素是与正则表达式相匹配的文本,第 1 个元素是与 RegExpObject 的第 1 个子表达式相匹配的文本(如果有的话),第 2 个元素是与 RegExpObject 的第 2 个子表达式相匹配的文本(如果有的话),以此类推。除了数组元素和 length 属性之外,exec() 方法还返回两个属性。index 属性声明的是匹配文本的第一个字符的位置。input 属性则存放的是被检索的字符串 string。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">reg</span> <span class="o">=</span> <span class="sr">/</span><span class="se">(\d</span><span class="sr">+</span><span class="se">)</span><span class="sr">lisong</span><span class="se">((\d</span><span class="sr">+</span><span class="se">)[</span><span class="sr">a-z</span><span class="se">])(\d)</span><span class="sr">/</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am 5lisong26a1df</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["5lisong26a1", "5", "26a", "26", "1", index: 5, input: "i am 5lisong26a1df"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am 12lisong18t2easdst</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["12lisong18t2", "12", "18t", "18", "2", index: 5, input: "i am 12lisong18t2easdst"]</span>
</code></pre></div></div>
<p>如果一个子表达式中还有字表达式,则先返回外层字表达式所匹配的文本。</p>
<p><em>exec全局匹配:</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">reg</span> <span class="o">=</span> <span class="sr">/lisong/</span><span class="p">;</span><span class="c1">//非全局匹配</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 5, input: "i am lisong"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span><span class="p">);</span><span class="c1">//0</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 5, input: "i am lisong"]</span>
<span class="nx">reg</span> <span class="o">=</span> <span class="sr">/lisong/g</span><span class="p">;</span><span class="c1">//重新赋值</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 5, input: "i am lisong"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span><span class="p">);</span><span class="c1">//11</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//null,从下标11开始,后面已经没有字符了</span>
<span class="nx">reg</span> <span class="o">=</span> <span class="sr">/lisong/g</span><span class="p">;</span><span class="c1">//重新赋值</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 5, input: "i am lisong"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span><span class="p">);</span><span class="c1">//11</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 17, input: "i am lisong i am lisong"]</span>
</code></pre></div></div>
<p>全局匹配下,exec会记录上一次匹配到的文本结尾的位置的下一个下标(lastIndex),即再次调用exec会从上一次匹配的文本之后开始搜索,非全局下lastIndex为0。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">reg</span> <span class="o">=</span> <span class="sr">/lisong/</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 5, input: "i am lisong"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span><span class="p">);</span><span class="c1">//0</span>
<span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span> <span class="o">=</span> <span class="mi">6</span><span class="p">;</span><span class="c1">//手动设置为6</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span><span class="p">);</span><span class="c1">//6</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 5, input: "i am lisong"],非全局下lastIndex对exec没有影响</span>
<span class="kd">var</span> <span class="nx">reg</span> <span class="o">=</span> <span class="sr">/lisong/g</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 5, input: "i am lisong"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span><span class="p">);</span><span class="c1">//0</span>
<span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span><span class="c1">//手动设置为0</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">lastIndex</span><span class="p">);</span><span class="c1">//0</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">reg</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">i am lisong</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["lisong", index: 5, input: "i am lisong"],全局下,exec是从lastIndex开始匹配的</span>
</code></pre></div></div>
<p>全局和非全局模式下都可以手动修改lastIndex,非全局模式下修改lastIndex对exec的匹配没有影响。</p>
<p><em>compile函数:</em></p>
<p>compile() 方法用于改变和重新编译正则表达式。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">abc12456def45646ghi</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">regExp</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="dl">"</span><span class="s2">[a-z]+</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">regExp</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">);</span> <span class="c1">// abc</span>
<span class="nx">regExp</span><span class="p">.</span><span class="nx">compile</span><span class="p">(</span><span class="dl">"</span><span class="se">\\</span><span class="s2">d+</span><span class="dl">"</span><span class="p">);</span><span class="c1">// 作用相当于regExp = /\d+/;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">regExp</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">);</span> <span class="c1">// 12456</span>
</code></pre></div></div>
<h3 id="regexp-对象属性">RegExp 对象属性</h3>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:120px; background-color:rgb(213,213,213)">
属性
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:446px; background-color:rgb(213,213,213)">
描述
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:28px; background-color:rgb(213,213,213)">
FF
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:27px; background-color:rgb(213,213,213)">
IE
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_regexp_global.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">global</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
RegExp 对象是否具有标志 g。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_regexp_ignorecase.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">ignoreCase</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
RegExp 对象是否具有标志 i。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_lastindex_regexp.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">lastIndex</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
一个整数,标示开始下一次匹配的字符位置。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_multiline_regexp.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">multiline</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
RegExp 对象是否具有标志 m。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_source_regexp.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">source</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
正则表达式的源文本。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
</tbody>
</table>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">abc12456def45646ghi</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">regExp</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">RegExp</span><span class="p">(</span><span class="dl">"</span><span class="s2">[a-z]+</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="s2">g</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span> <span class="nx">regExp</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">)</span> <span class="p">);</span> <span class="c1">// abc</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">regExp</span><span class="p">.</span><span class="nb">global</span><span class="p">);</span><span class="c1">//true</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">regExp</span><span class="p">.</span><span class="nx">ignoreCase</span><span class="p">);</span><span class="c1">//false</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">regExp</span><span class="p">.</span><span class="nx">lastIndex</span><span class="p">);</span><span class="c1">//3</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">regExp</span><span class="p">.</span><span class="nx">multiline</span><span class="p">);</span><span class="c1">//false</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">regExp</span><span class="p">.</span><span class="nx">source</span><span class="p">);</span><span class="c1">//Source</span>
</code></pre></div></div>
<h3 id="regexp静态属性">RegExp静态属性</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var str = "123abc456lisong789hehe";
var regExp = new RegExp("[a-z]+(\\d+)","g");
console.log( regExp.exec(str) ); //["abc456", "456", index: 3, input: "123abc456lisong789hehe"]
console.log(RegExp.input); //123abc456lisong789hehe
console.log(RegExp.leftContext); //123
console.log(RegExp.rightContext); //lisong789hehe
console.log(RegExp.lastMatch); //abc456
console.log(RegExp.lastParen); //456
console.log("-------------------------------")
console.log( regExp.exec(str) ); //["lisong789", "789", index: 9, input: "123abc456lisong789hehe"]
console.log(RegExp.leftContext); //123abc456
console.log(RegExp.rightContext); //hehe
console.log(RegExp.lastMatch); //lisong789
console.log(RegExp.lastParen); //789
console.log("-------------------------------")
var regExp2 = /lisong(\d(\d))/;
regExp2.test("123lisong456"); //test函数也会更改RegExp全局属性
console.log( regExp.exec(str) ); //null,如果没匹配到不会改变静态属性
console.log(RegExp.leftContext); //123
console.log(RegExp.rightContext); //6
console.log(RegExp.lastMatch); //lisong45
console.log(RegExp.lastParen); //5,如果没有子表达式,则返回空字符串
</script>
</code></pre></div></div>
<p>也可以使用短名称,如RegExp.$_,RegExp[’$*’]</p>
<h3 id="string对象的正则方法">String对象的正则方法</h3>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:120px; background-color:rgb(213,213,213)">
方法
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:446px; background-color:rgb(213,213,213)">
描述
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:28px; background-color:rgb(213,213,213)">
FF
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:27px; background-color:rgb(213,213,213)">
IE
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_search.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">search</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
检索与正则表达式相匹配的值。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_match.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">match</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
找到一个或多个正则表达式的匹配。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_replace.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">replace</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
替换与正则表达式匹配的子串。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<a target="_blank" href="http://www.w3school.com.cn/jsref/jsref_split.asp" style="margin:0px; padding:0px; border:0px; color:rgb(144,11,9); background:transparent">split</a>
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
把字符串分割为字符串数组。
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
1
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
4
</td>
</tr>
</tbody>
</table>
<p><em>search方法:</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">str</span><span class="o">=</span><span class="dl">"</span><span class="s2">Visit W3School!</span><span class="dl">"</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">search</span><span class="p">(</span><span class="sr">/W3School/</span><span class="p">))</span><span class="c1">//6,返回值是第一次出现的位置,search的参数可以是字符串或者正则对象</span>
</code></pre></div></div>
<p><em>match方法:</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">1lisong2lisong3lisong</span><span class="dl">"</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">reg</span> <span class="o">=</span> <span class="sr">/li</span><span class="se">(</span><span class="sr">song</span><span class="se">)</span><span class="sr">/</span><span class="p">;</span><span class="c1">//非全局模式</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">reg</span><span class="p">));</span><span class="c1">//["lisong", "song", index: 1, input: "1lisong2lisong3lisong"],search的参数可以是字符串或者正则对象</span>
<span class="nx">reg</span> <span class="o">=</span> <span class="sr">/li</span><span class="se">(</span><span class="sr">song</span><span class="se">)</span><span class="sr">/g</span><span class="p">;</span><span class="c1">//全局模式</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">match</span><span class="p">(</span><span class="nx">reg</span><span class="p">));</span><span class="c1">//["lisong", "lisong", "lisong"]</span>
</code></pre></div></div>
<p>非全局模式下,match只匹配一次,如果匹配到了则返回数组(和正则对象的exec()方法返回的数组一样),否则返回null。
全局模式下,match匹配多次,如果匹配到了,只返回匹配的子串数组,否则返回null。</p>
<p><em>replace方法:</em></p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
参数
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
regexp/substr
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
<p style="margin-top:0px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; border:0px; line-height:18px">
必需。规定子字符串或要替换的模式的 RegExp 对象。
</p>
<p style="margin-top:12px; margin-bottom:0px; padding-top:0px; padding-bottom:0px; border:0px; line-height:18px">
请注意,如果该值是一个字符串,则将它作为要检索的直接量文本模式,而不是首先被转换为 RegExp 对象。
</p>
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
replacement
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
必需。一个字符串值。规定了替换文本或生成替换文本的函数。
</td>
</tr>
</tbody>
</table>
<font style="font-size:10px;font-weight:bold">说明</font>
<p>如果 regexp 具有全局标志 g,那么 replace() 方法将替换所有匹配的子串。否则,它只替换第一个匹配子串。
replacement 可以是字符串,也可以是函数。如果它是字符串,那么每个匹配都将由字符串替换。
但是 replacement 中的 $ 字符具有特定的含义。如下表所示,它说明从模式匹配得到的字符串将用于替换。</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
字符
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
替换文本
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
$1、$2、...、$99
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
与 regexp 中的第 1 到第 99 个子表达式相匹配的文本。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
$&
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
与 regexp 相匹配的子串。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
$`
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
位于匹配子串左侧的文本。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
$'
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
位于匹配子串右侧的文本。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
$$
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
直接量符号。
</td>
</tr>
</tbody>
</table>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">aLisong123lisong</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="dl">"</span><span class="s2">lisong</span><span class="dl">"</span><span class="p">,</span><span class="dl">'</span><span class="s1">hero</span><span class="dl">'</span><span class="p">));</span><span class="c1">//aLisong123hero</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/lisong/i</span><span class="p">,</span><span class="dl">'</span><span class="s1">hero</span><span class="dl">'</span><span class="p">));</span><span class="c1">//ahero123lisong</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">(</span><span class="sr">li</span><span class="se">)(</span><span class="sr">song</span><span class="se">)</span><span class="sr">/ig</span><span class="p">,</span><span class="dl">'</span><span class="s1">$2$1</span><span class="dl">'</span><span class="p">));</span><span class="c1">//asongLi123songli</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/lisong/ig</span><span class="p">,</span><span class="dl">'</span><span class="s1">|$&|</span><span class="dl">'</span><span class="p">));</span><span class="c1">//a|Lisong|123|lisong|</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/lisong/ig</span><span class="p">,</span><span class="dl">'</span><span class="s1">$$</span><span class="dl">'</span><span class="p">));</span><span class="c1">//a$123$</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/lisong/i</span><span class="p">,</span><span class="dl">'</span><span class="s1">$`|</span><span class="dl">'</span><span class="p">));</span><span class="c1">//aa|123lisong</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/lisong/ig</span><span class="p">,</span><span class="dl">'</span><span class="s1">$`|</span><span class="dl">'</span><span class="p">));</span><span class="c1">//aa|123aLisong123|,使用全局替换$`时,会在内容没有改变的基础上替换,而不管前一次替换的内容</span>
<span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">aLisong123lisongalisongb</span><span class="dl">"</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/lisong/i</span><span class="p">,</span><span class="dl">'</span><span class="s1">$</span><span class="se">\'</span><span class="s1">|</span><span class="dl">'</span><span class="p">));</span><span class="c1">//a123lisongalisongb|123lisongalisongb</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/lisong/ig</span><span class="p">,</span><span class="dl">'</span><span class="s1">$</span><span class="se">\'</span><span class="s1">|</span><span class="dl">'</span><span class="p">));</span><span class="c1">//a123lisongalisongb|123alisongb|ab|b,替换原理和$`一样</span>
</code></pre></div></div>
<p>ECMAScript v3 规定,replace() 方法的参数 replacement 可以是函数而不是字符串。在这种情况下,每个匹配都调用该函数,它返回的字符串将作为替换文本使用。该函数的第一个参数是匹配模式的字符串。接下来的参数是与模式中的子表达式匹配的字符串,可以有 0 个或多个这样的参数。接下来的参数是一个整数,声明了匹配在 stringObject 中出现的位置。最后一个参数是 stringObject 本身。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">aLisong123lisong</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">(</span><span class="sr">li</span><span class="se">)(</span><span class="sr">song</span><span class="se">)</span><span class="sr">/ig</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">arguments</span><span class="p">);</span>
<span class="c1">//["Lisong", "Li", "song", 1, "aLisong123lisong"]</span>
<span class="c1">//["lisong", "li", "song", 10, "aLisong123lisong"]</span>
<span class="k">return</span> <span class="nx">arguments</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span><span class="o">+</span><span class="nx">arguments</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
<span class="p">}));</span><span class="c1">//asongLi123songli,效果和str.replace(/(li)(song)/ig,'$2$1')一样</span>
</code></pre></div></div>
<p><em>split函数:</em></p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
参数
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
separator
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
必需。字符串或正则表达式,从该参数指定的地方分割 stringObject。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
howmany
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。
</td>
</tr>
</tbody>
</table>
<font style="font-size:10px;font-weight:bold">返回值</font>
<p>一个字符串数组。该数组是通过在 separator 指定的边界处将字符串 stringObject 分割成子串创建的。返回的数组中的字串不包括separator 自身。
但是,如果 separator 是包含子表达式的正则表达式,那么返回的数组中包括与这些子表达式匹配的字串(但不包括与整个正则表达式匹配的文本)。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">aLisongblisongc</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="sr">/lisong/i</span><span class="p">));</span><span class="c1">//["a", "b", "c"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="sr">/lisong/i</span><span class="p">,</span><span class="mi">2</span><span class="p">));</span><span class="c1">//["a", "b"],只返回前两个</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="sr">/li</span><span class="se">(</span><span class="sr">song</span><span class="se">)</span><span class="sr">/i</span><span class="p">));</span><span class="c1">//["a", "song", "b", "song", "c"]</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">str</span><span class="p">.</span><span class="nx">split</span><span class="p">(</span><span class="sr">/li</span><span class="se">(</span><span class="sr">song</span><span class="se">)</span><span class="sr">/i</span><span class="p">,</span><span class="mi">2</span><span class="p">));</span><span class="c1">//["a", "song"]</span>
</code></pre></div></div>
<p>注意:给split设置第二个参数n,只是简单的返回原数组的前n个元素</p>
<h3 id="多行匹配">多行匹配</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/^</span><span class="se">\d</span><span class="sr">+/mg</span><span class="p">;</span><span class="c1">//启用了换行和全局模式</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">1.baidu</span><span class="se">\n</span><span class="s1">2.google</span><span class="se">\n</span><span class="s1">3.bing</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">pattern</span><span class="p">,</span> <span class="dl">'</span><span class="s1">#</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="c1">//#.baidu</span>
<span class="c1">//#.google</span>
<span class="c1">//#.bing</span>
<span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/^</span><span class="se">\d</span><span class="sr">+/g</span><span class="p">;</span><span class="c1">//启用了全局模式</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">1.baidu</span><span class="se">\n</span><span class="s1">2.google</span><span class="se">\n</span><span class="s1">3.bing</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">pattern</span><span class="p">,</span> <span class="dl">'</span><span class="s1">#</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="c1">//#.baidu</span>
<span class="c1">//2.google</span>
<span class="c1">//3.bing</span>
<span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/^</span><span class="se">\d</span><span class="sr">+/m</span><span class="p">;</span><span class="c1">//启用了多行模式</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">1.baidu</span><span class="se">\n</span><span class="s1">2.google</span><span class="se">\n</span><span class="s1">3.bing</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">str</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="nx">pattern</span><span class="p">,</span> <span class="dl">'</span><span class="s1">#</span><span class="dl">'</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">);</span>
<span class="c1">//#.baidu</span>
<span class="c1">//2.google</span>
<span class="c1">//3.bing</span>
</code></pre></div></div>
<p>注意:多行匹配必须和全局模式一起使用才有效,如果是匹配换行符,只需要开启全局模式即可</p>
<h3 id="前瞻捕获">前瞻捕获</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/</span><span class="se">(</span><span class="sr">goo</span><span class="se">(?=</span><span class="sr">gle</span><span class="se">))</span><span class="sr">/</span><span class="p">;</span><span class="c1">//goo后面必须跟着gle才能捕获,(?=)只能放在后面</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">google</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pattern</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">));</span><span class="c1">//["goo", "goo", index: 0, input: "google"]</span>
</code></pre></div></div>
<h3 id="非前瞻捕获">非前瞻捕获</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/</span><span class="se">(</span><span class="sr">goo</span><span class="se">(?!</span><span class="sr">gle</span><span class="se">))</span><span class="sr">/</span><span class="p">;</span><span class="c1">//goo后面必须不跟着gle才能捕获,(?!)与(?=)正好相反</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pattern</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">google</span><span class="dl">"</span><span class="p">));</span><span class="c1">//null</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pattern</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="dl">"</span><span class="s2">gooagle</span><span class="dl">"</span><span class="p">));</span><span class="c1">//["goo", "goo", index: 0, input: "gooagle"]</span>
</code></pre></div></div>
<h3 id="非捕获性分组">非捕获性分组</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/</span><span class="se">(\d</span><span class="sr">+</span><span class="se">)(?:[</span><span class="sr">a-z</span><span class="se">])</span><span class="sr">/</span><span class="p">;</span><span class="c1">//非捕获性分组</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">123abc</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pattern</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">));</span><span class="c1">//["123a", "123", index: 0, input: "123abc"]</span>
<span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/</span><span class="se">(\d</span><span class="sr">+</span><span class="se">)(?:(\d)[</span><span class="sr">a-z</span><span class="se">])</span><span class="sr">/</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">123abc</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pattern</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">));</span><span class="c1">//["123a", "12", "3", index: 0, input: "123abc"],外层括号没有捕获</span>
<span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/</span><span class="se">(\d</span><span class="sr">+</span><span class="se">)((?:\d)[</span><span class="sr">a-z</span><span class="se">])</span><span class="sr">/</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">123abc</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pattern</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">));</span><span class="c1">//["123a", "12", "3a", index: 0, input: "123abc"],里层括号没有捕获</span>
</code></pre></div></div>
<h3 id="反向引用">反向引用</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/</span><span class="se">([</span><span class="sr">a-z</span><span class="se">]</span><span class="sr">+</span><span class="se">)(\1)\b</span><span class="sr">/</span><span class="p">;</span><span class="c1">//\b代表字符的边界</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">ahehe b</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pattern</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">));</span><span class="c1">//["hehe", "he", "he", index: 1, input: "ahehe b"]</span>
<span class="kd">var</span> <span class="nx">pattern</span> <span class="o">=</span> <span class="sr">/</span><span class="se">\b([</span><span class="sr">a-z</span><span class="se">]</span><span class="sr">+</span><span class="se">)(\1)\b</span><span class="sr">/</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">str</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">ahehe b</span><span class="dl">"</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">pattern</span><span class="p">.</span><span class="nx">exec</span><span class="p">(</span><span class="nx">str</span><span class="p">));</span><span class="c1">//null</span>
</code></pre></div></div>
javascript笔记--(第九章)日期与时间
2017-06-27T09:00:55+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第九章)日期与时间
<h2 id="date类型">Date类型</h2>
<p>ECMAScript中的Date类型是在早期Java中java.util.Date类基础上构建的。为此,Date类型使用UTC (Coordinated Universal Time,国际协调时间[又称世界统一时间]) 1970年1月1日午夜(零时)开始经过的毫秒来保存日期。</p>
<p>ECMAScript提供了两个方法,Date.parse()和Date.UTC()。Date.parse()默认是京8区,Date.UTC()默认没有时区。Date.parse()方法接收一个表示日期的字符串参数,然后尝试根据这个字符串返回 1970/1/1 午夜距离该日期时间的毫秒数。ECMA-262没有定义Date.parse()应该支持哪种日期格式,因此方法的行为因实现而异,因地区而异。默认通常接收的日期格式如下:</p>
<ol>
<li>‘月/日/年’,如6/13/2011;</li>
<li>‘英文月名 日, 年’,如 May 25, 2004;</li>
<li>‘英文星期几 英文月名 日 年 时:分:秒 时区’,如 Tue May 25 2004 00:00:00 GMT-070</li>
</ol>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var date1 = Date.parse('6/13/2017 0:0:1');//相当于Mon Jun 13 2017 00:00:01 GMT+0800
console.log(date1);//1497283201000
var date2 = Date.parse('Jun 13,2017 00:00:02');
console.log(date2);//1497283202000
var date3 = Date.parse('Mon Jun 13 2017 00:00:00 GMT+0800');
console.log(date3);//1497283200000
</script>
</code></pre></div></div>
<p>日期后面可以跟时间</p>
<p>Date.UTC()方法同样也返回表示日期的毫秒数,但它与Date.parse()在构建值时使用不同的信息。(年份,基于0的月份[0表示1月,1表示2月],月中的哪一天[1-31],小时数[0-23],分钟,秒以及毫秒)。只有前两个参数是必须的。如果没有提供月数,则天数为1;如果省略其他参数,则统统为0。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var date1 = Date.UTC(2017,5,13,0,0,1,10);//年,月,日,时,分,秒,毫秒
console.log(date1);//1497312001010,也是返回1970/1/1 午夜距离该日期时间的毫秒数
</script>
</code></pre></div></div>
<h3 id="日期方法">日期方法</h3>
<p>与其他类型一样,Date类型也重写了toLocaleString()、toString()和valueOf()方法。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var date1 = new Date(Date.UTC(2017,5,13,0,0,1,10));//年,月,日,时,分,秒,毫秒
console.log(date1.toString());//Tue Jun 13 2017 08:00:01 GMT+0800 (中国标准时间)
console.log(date1.toLocaleString());//2017/6/13 上午8:00:01
console.log(date1.valueOf());//1497312001010
</script>
</code></pre></div></div>
<p>注意:toString和toLocaleString在不同的浏览器上可能不一样,一般不用这两个方法来显示时间</p>
<p>其他的一些方法:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var date1 = new Date();
console.log(date1.toDateString());//Thu Feb 02 2017
console.log(date1.toLocaleDateString());//2017/2/2
console.log(date1.toTimeString());//15:51:07 GMT+0800 (中国标准时间)
console.log(date1.toLocaleTimeString());//下午3:51:07
console.log(date1.toUTCString());//Thu, 02 Feb 2017 07:52:32 GMT
</script>
</code></pre></div></div>
<h2 id="组件方法">组件方法</h2>
<p>组件方法,是为我们单独获取你想要的各种时间/日期而提供的方法。需要注意的时候,这些方法中,有带UTC的,有不带UTC的。UTC日期指的是在没有时区偏差的情况下的日期值。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = new Date(Date.UTC(2017,2,10,5,15,10));
console.log('毫秒:'+box.getTime()); //1489122910000,获取日期的毫秒数,和valueOf()返回一致
console.log('年:'+box.getFullYear()); //2017,获取四位年份
console.log('月:'+(1+box.getMonth())); //3,获取月份,没指定月份,从0开始算起
console.log('日:'+box.getDate()); //10,获取日期
console.log('星期:'+box.getDay()); //5,返回星期几,0表示星期日,6表示星期六
console.log('时:'+box.getHours()); //13,返回时,这里获得的是北京时间,加上了8个时区
console.log('UTC时:'+box.getUTCHours()); //5,返回时
console.log('分:'+box.getMinutes()); //15,返回分钟
console.log('秒:'+box.getSeconds()); //10,返回秒数
console.log('毫秒:'+box.getMilliseconds()); //0,返回毫秒数
console.log(box.getTimezoneOffset()); //-480,返回本地时间和UTC时间相差的分钟数,480/60=8
</script>
</code></pre></div></div>
<p>上面所有的方法除了getDay()和getTimezoneOffset(),都有相应的set方法,如setTime(),setFullYear(),并且除了getTimezoneOffset(),所有的set和get方法都有相应的UTC方法,如getUTCTime(),setUTCTime(),getUTCHours(),setUTCHours()。</p>
javascript笔记--(第八章)对象和数组
2017-06-27T08:53:37+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第八章)对象和数组
<h2 id="object类型">Object类型</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = new Object();
box.name = "box";
var box1 = new Object; // 可以省略()
box1.name = "box1";
var box2 = Object();//可以省略new
box2.name = "box2";
var box3= {'name':"box3"};//key可以加引号
console.log(box.name);
console.log(box1['name']) //可以用[]输出属性值
console.log(box2.name);
console.log(box3.name);
delete box.name;//删除name属性
console.log(box.name) //undefined
</script>
</code></pre></div></div>
<h2 id="array类型">Array类型</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = new Array(); //创建了一个数组
var box = new Array(10); //创建一个包含10个元素的数组
var box = new Array('李炎恢',28,'教师','盐城'); //创建一个数组并分配好了元素
var box = Array(); //可以省略new关键字
var box = ['李炎恢',28,'教师','盐城']; //使用字面量定义数组,不会调用Array构造函数(Firefox除外)
</script>
</code></pre></div></div>
<p>对象或数组都具有toLocaleString()、toString()和valueOf()方法。这三个方法都可以重写</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = ['李松',26,'程序员']; //使用字面量定义数组,不会调用Array构造函数(Firefox除外)
console.log(box.valueOf()); //["李松", 26, "程序员"]
console.log(box.toString()); //李松,26,程序员
console.log(box.toLocaleString()); //李松,26,程序员
box.valueOf = function(){
return "lisong_1";
}
box.toString = function(){
return "lisong_2";
};
box.toLocaleString = function(){
return "lisong_3";
}
console.log(box.valueOf()); //lisong_1
console.log(box.toString()); //lisong_2
console.log(box.toLocaleString()); //lisong_3
console.log(box.join("|")) //李松|26|程序员//可以指定连接符
</script>
</code></pre></div></div>
<h3 id="数组栈方法">数组栈方法</h3>
<p>push()方法可以接收任意数量的参数,把它们逐个添加到数组的末尾,并返回修改后数组的长度。而pop()方法则从数组末尾移除最后一个元素,减少数组的length值,然后返回移除的元素。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = [];
console.log(box.push('李松',26,'程序员'));//3,添加元素并返回数组长度
console.log(box);//["李松", 26, "程序员"]
console.log(box.pop());//程序员,删除栈顶元素并返回删除的元素
console.log(box);//["李松", 26]
</script>
</code></pre></div></div>
<h3 id="数组的队列方法">数组的队列方法</h3>
<p>栈方法是后进先出,而列队方法就是先进先出。列队在数组的末端添加元素,从数组的前端移除元素。通过push()向数组末端添加一个元素,然后通过shift()方法从数组前端移除一个元素。 ECMAScript还为数组提供了一个unshift()方法,它和shift()方法的功能完全相反。unshift()方法为数组的前端添加一个元素</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = [];
console.log(box.push('李松',26,'程序员'));//3,添加元素并返回数组长度
console.log(box);//["李松", 26, "程序员"]
console.log(box.shift());//李松,移除队头元素并返回
console.log(box);//[26,"程序员"]
console.log(box.unshift("李松","耒阳"));//4,在队头添加元素并返回添加后的数组长度
console.log(box);//console.log(box);
</script>
</code></pre></div></div>
<font style="background:#eee">PS:IE浏览器对unshift()方法总是返回undefined而不是数组的新长度。</font>
<h3 id="数组的重排序方法">数组的重排序方法</h3>
<p>数组中已经存在两个可以直接用来排序的方法:reverse()和sort(),这两个方法将改变源数组。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = [1,3,4,2];
box.reverse(); //将数组逆序
console.log(box); //[2, 4, 3, 1]
box.sort(); //默认从小到大排序
console.log(box); //[1, 2, 3, 4]
box.reverse(); //将数组逆序
console.log(box); //[4, 3, 2, 1]
function mySort(value1,value2){
if(value1<value2)
return -1;
else if(value1 == value2)
return 0;
else
return 1;
}
box.sort(mySort); //自定义排序
console.log(box); //[1, 2, 3, 4]
</script>
</code></pre></div></div>
<h3 id="数组的操作方法">数组的操作方法</h3>
<p>ECMAScript为操作已经包含在数组中的元素提供了很多方法。concat()方法可以基于当前数组创建一个新数组。slice()方法可以基于当前数组获取指定区域元素并创建一个新数组。splice()主要用途是向数组的中部插入或删除元素。</p>
<p><em>concat函数:</em></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = ["李松",26,"程序员"];
var box2 = box.concat("耒阳","黄市");
console.log(box2); //["李松", 26, "程序员", "耒阳", "黄市"]
console.log(box); //["李松", 26, "程序员"],当前数组没有变化
</script>
</code></pre></div></div>
<p><em>slice函数:</em></p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th class="no_wrap" style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); white-space:nowrap; vertical-align:baseline; background-color:rgb(213,213,213)">
参数
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
start
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
必需。规定从何处开始选取。如果是负数,那么它规定从数组尾部开始算起的位置。也就是说,-1 指最后一个元素,-2 指倒数第二个元素,以此类推。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
end
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
可选。规定从何处结束选取。该参数是数组片断结束处的数组下标。如果没有指定该参数,那么切分的数组包含从 start 到数组结束的所有元素。如果这个参数是负数,那么它规定的是从数组尾部开始算起的元素。
</td>
</tr>
</tbody>
</table>
<h3 style="margin:20px 0px 0px; padding:0px; border:0px">
<span style="font-size:10px">返回值</span>
</h3>
<p>返回一个新的数组,包含从 start 到 end (不包括该元素)的 arrayObject 中的元素。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = ["李松",26,"程序员"];
var box2 = box.slice(1,2); //2是结束下标(不包括)
console.log(box2); //26]
console.log(box); //["李松", 26, "程序员"],当前数组没有变化
box2 = box.slice(-3,-1);
console.log(box2); //["李松",26],倒数第三个开始,倒数第一个结束
box2 = box.slice(3,1);
console.log(box2); //[],开始下标在结束下标之后,将返回空数组
box2 = box.slice(-1,-3);
console.log(box2); //[],开始下标在结束下标之后,将返回空数组
</script>
</code></pre></div></div>
<p><em>splice函数:</em></p>
<p>PS:该方法会改变原始数组</p>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:155px; background-color:rgb(213,213,213)">
参数
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
index
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
必需。整数,规定添加/删除项目的位置,使用负数可从数组结尾处规定位置。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
howmany
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
必需。要删除的项目数量。如果设置为 0,则不会删除项目。
</td>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
item1, ..., itemX
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
可选。向数组添加的新项目。
</td>
</tr>
</tbody>
</table>
<h3 style="margin:20px 0px 0px; padding:0px; border:0px">
<span style="font-size:10px">返回值</span>
</h3>
<table class="dataintable " style="margin:10px 0px 0px; padding:0px; border:1px solid rgb(170,170,170); border-collapse:collapse; width:709px; color:rgb(0,0,0); font-family:Verdana,Arial,宋体; font-size:12px; background-color:rgb(249,249,249)">
<tbody style="margin:0px; padding:0px; border:0px">
<tr style="margin:0px; padding:0px; border:0px">
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; width:155px; background-color:rgb(213,213,213)">
类型
</th>
<th style="margin:0px; padding:5px 15px 5px 6px; border:1px solid rgb(170,170,170); vertical-align:baseline; background-color:rgb(213,213,213)">
描述
</th>
</tr>
<tr style="margin:0px; padding:0px; border:0px">
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
Array
</td>
<td style="margin:0px; padding:6px 15px 6px 6px; border:1px solid rgb(170,170,170); vertical-align:text-top; background-color:rgb(239,239,239)">
包含被删除项目的新数组,如果有的话。
</td>
</tr>
</tbody>
</table>
<h3 style="margin:20px 0px 0px; padding:0px; border:0px">
<span style="font-size:10px">说明</span>
</h3>
<p>splice() 方法可删除从 index 处开始的零个或多个元素,并且用参数列表中声明的一个或多个值来替换那些被删除的元素。如果从 arrayObject 中删除了元素,则返回的是含有被删除的元素的数组。如果只有第一个参数,则将删除index开始位置之后的所有元素。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = ["李松",26,"程序员"];
var box2 = box.splice(1,2,20); //返回删除的元素
console.log(box2); //[26, "程序员"]
console.log(box); //["李松", 20]
box = ["李松",26,"程序员"];
var box2 = box.splice(1,1,20);//返回删除的元素
console.log(box2); //[26]
console.log(box); //["李松", 20, "程序员"]
box = ["李松",26,"程序员"];
var box2 = box.splice(1,0,"耒阳");//返回删除的元素
console.log(box2); //[]
console.log(box); //["李松", "耒阳", 26, "程序员"]
box = ["李松",26,"程序员"];
var box2 = box.splice(-1,0,"耒阳");//返回删除的元素
console.log(box2); //[]
console.log(box); //["李松", 26, "耒阳", "程序员"]
box = ["李松",26,"程序员"];
var box2 = box.splice(1);//返回删除的元素
console.log(box2); //[26,"程序员"]
console.log(box); //["李松"]
</script>
</code></pre></div></div>
<h2 id="数组和对象的区别">数组和对象的区别</h2>
<p>数组是对象的子类,对象的所有特性,数组都有,此外数组还扩展了自己独有的方法。js中数组和对象都可以用来存储集合,数组一般用来存储有序集合,对象用来存储无序集合。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var a=[0];
a['5']=5;
a[1]=1;
a.test='test'
console.log(a['test']);//test
console.log(a['0']);//0
console.log(a['1']);//1
console.log(a[5]);//5
console.log(a.length);//6
console.log(a);
var b={0:0,5:5};
console.log(b['0']);//0
console.log(b[5]);//5
console.log(b.length);//undefined
console.log(b);
</script>
</code></pre></div></div>
<p>数组和对象都可以用数字和字符串索引元素,数组length属性返回的是最大的索引数字加1后的结果,对象默认是没有length属性的。</p>
javascript笔记--(第七章)函数
2017-06-27T08:37:32+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第七章)函数
<h2 id="函数">函数</h2>
<p>函数是定义一次但却可以调用或执行任意多次的一段JS代码</p>
<h2 id="arguments对象">arguments对象</h2>
<p>ECMAScript函数不介意传递进来多少参数,也不会因为参数不统一而错误。实际上,函数体内可以通过arguments对象来接收传递进来的参数。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
function box() {
var sum = 0;
if (arguments.length == 0) return sum; //如果没有参数,退出
for(var i = 0;i < arguments.length; i++) { //如果有,就累加
sum = sum + arguments[i];
}
return sum; //返回累加结果
}
console.log(box(5,9,12));
</script>
</code></pre></div></div>
<p>ECMAScript中的函数,没有像其他高级语言那种函数重载功能,在js中后面定义的同名函数会覆盖前面定义的函数</p>
javascript笔记--(第六章)流程控制语句
2017-06-27T08:36:15+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第六章)流程控制语句
<h2 id="语句的定义">语句的定义</h2>
<p>在ECMAScript中,所有的代码都是由语句来构成的。语句表明执行过程中的流程、限定与约定,形式上可以是单行语句,或者由一对大括号“{}”括起来的复合语句,在语法描述中,复合语句整体可以作为一个单行语句处理。</p>
<h3 id="switch语句">switch语句</h3>
<p>ECMAScript 和 Java 中的 switch 语句有两点不同。在 ECMAScript 中,switch 语句可以用于字符串,而且能用不是常量的值说明情况:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var BLUE = "blue", RED = "red", GREEN = "green";
var sColor = "red";
switch (sColor) {
case BLUE: alert("Blue");
break;
case RED: alert("Red");
break;
case GREEN: alert("Green");
break;
default: alert("Other");
}
</script>
</code></pre></div></div>
<h3 id="forin语句">for…in语句</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = {
'name' : '李炎恢', //键值对,左边是属性名,右边是值
'age' : 28,
'height' : 178
};
for (var p in box) { //列举出对象的所有属性
console.log(p);
}
</script>
</code></pre></div></div>
<h3 id="with语句">with语句</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = {
'name' : '李松',
'age' : 26,
};
with (box) { //省略了box对象名
var n = name;
var a = age;
}
console.log(n);
console.log(a);
</script>
</code></pre></div></div>
javascript笔记--(第五章)运算符
2017-06-27T08:12:37+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/27/javascript笔记--(第五章)运算符
<h2 id="表达式">表达式</h2>
<p>表达式是ECMAScript中的一个“短语”,解释器会通过计算把它转换成一个值。最简单的表达式是字面量或者变量名</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span><span class="p">(</span><span class="nx">n</span><span class="p">)</span> <span class="p">{</span><span class="k">return</span> <span class="nx">x</span><span class="o">+</span><span class="nx">y</span><span class="p">;}</span> <span class="c1">//函数字面量、函数表达式</span>
<span class="nx">box</span> <span class="c1">//变量</span>
</code></pre></div></div>
<h3 id="一元运算符">一元运算符</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = '89'; box++;
console.log(box); //90,数值字符串自动转换成数值
var box = 'ab'; box++;
console.log(box); //NaN,字符串包含非数值转成NaN
var box = false; box++;
console.log(box); //1,false转成数值是0,累加就是1
var box = 2.3; box++;
console.log(box); //3.3,直接加1
var box = {
toString : function() {
return 1;
}
};
box++;
console.log(box); //2,不设置toString或valueOf即为NaN
</script>
</code></pre></div></div>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var box = '89'; box=+box;
console.log(box); //89,数值字符串自动转换成数值
var box = 'ab'; box=+box;
console.log(box); //NaN,字符串包含非数值转成NaN
var box = false; box=+box;
console.log(box); //0,false转成数值是0
var box = {
toString : function() {
return 1;
}
};
box=+box;
console.log(box); //1,不设置toString或valueOf即为NaN
</script>
</code></pre></div></div>
<p>加法和减法运算符一般用于算术运算,也可像上面进行类型转换。</p>
<h3 id="算术运算符">算术运算符</h3>
<p>ECMAScript定义了5个算术运算符,加减乘除求模(取余)。如果算术运算的值不是数值,那么后台会先使用Number()转型函数将简单类型值转换为数值(隐式转换),如果该值是对象,则先调用valueOf或者toString方法,再用Number()将其值转换成数值。</p>
<p><em>减法:</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">1</span> <span class="o">-</span> <span class="kc">NaN</span><span class="p">;</span> <span class="c1">//NaN,只要有一个NaN就为NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="kc">Infinity</span> <span class="o">-</span> <span class="kc">Infinity</span><span class="p">;</span> <span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">-</span><span class="kc">Infinity</span> <span class="o">-</span> <span class="o">-</span><span class="kc">Infinity</span><span class="p">;</span> <span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="kc">Infinity</span> <span class="o">-</span> <span class="o">-</span><span class="kc">Infinity</span><span class="p">;</span> <span class="c1">//Infinity</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">-</span><span class="kc">Infinity</span> <span class="o">-</span> <span class="kc">Infinity</span><span class="p">;</span> <span class="c1">//-Infinity</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span> <span class="o">-</span> <span class="kc">true</span><span class="p">;</span> <span class="c1">//99,true转成数值为1</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span> <span class="o">-</span> <span class="dl">''</span><span class="p">;</span> <span class="c1">//100,''转成了0</span>
</code></pre></div></div>
<p><em>乘法:</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span> <span class="o">*</span> <span class="kc">NaN</span><span class="p">;</span> <span class="c1">//NaN,只要有一个NaN即为NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="kc">Infinity</span> <span class="o">*</span> <span class="kc">Infinity</span><span class="p">;</span> <span class="c1">//Infinity</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">-</span><span class="kc">Infinity</span> <span class="o">*</span> <span class="kc">Infinity</span> <span class="p">;</span> <span class="c1">//-Infinity</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">-</span><span class="kc">Infinity</span> <span class="o">*</span> <span class="o">-</span><span class="kc">Infinity</span> <span class="p">;</span> <span class="c1">//Infinity</span>
</code></pre></div></div>
<p><em>除法:</em></p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="kc">Infinity</span> <span class="o">/</span> <span class="mi">0</span><span class="p">;</span><span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="kc">Infinity</span> <span class="o">/</span> <span class="kc">null</span><span class="p">;</span><span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="kc">Infinity</span> <span class="o">%</span> <span class="kc">Infinity</span><span class="p">;</span><span class="c1">//NaN </span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">-</span><span class="kc">Infinity</span> <span class="o">%</span> <span class="kc">Infinity</span><span class="p">;</span><span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">-</span><span class="kc">Infinity</span> <span class="o">%</span> <span class="o">-</span><span class="kc">Infinity</span><span class="p">;</span><span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span> <span class="o">%</span> <span class="mi">0</span><span class="p">;</span><span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span> <span class="o">%</span> <span class="dl">''</span><span class="p">;</span><span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span> <span class="o">%</span> <span class="kc">null</span><span class="p">;</span><span class="c1">//NaN</span>
</code></pre></div></div>
<h3 id="关系运算符">关系运算符</h3>
<p>和其他运算符一样,当关系运算符操作非数值时要遵循一下规则:</p>
<ol>
<li>两个操作数都是数值,则数值比较;</li>
<li>两个操作数都是字符串,则比较两个字符串对应的字符编码值;</li>
<li>两个操作数有一个是数值,则将另一个转换为数值,再进行数值比较;</li>
<li>两个操作数有一个是对象,则先调用valueOf()方法或toString()方法,再用结果比较;</li>
</ol>
<p><em>相等和不等的比较:</em></p>
<ul>
<li>两个操作数都是对象,则比较他们是否是同一个对象,如果都指向同一个对象,则返回true,否则返回false</li>
<li>在全等和全不等的判断上,比如值和类型都相等,才返回true,否则返回false</li>
</ul>
<font style="background:#eee">
注意:null>=为true,null<=0为true,null>0为false,null<为false,之所以会这样,是因为在进行>和<时候会将null转换成0,而>=的结果其实是取<的反,<=同理。
</font>
<h3 id="逻辑运算符">逻辑运算符</h3>
<p>有三个逻辑运算符:逻辑与(AND)、逻辑或(OR)、逻辑非(NOT)。</p>
<p><em>逻辑与&&:</em></p>
<p>如果两边的操作数有一个操作数不是布尔值的情况下,与运算就不一定返回布尔值,此时,遵循已下规则:</p>
<ol>
<li>第一个操作数是对象,则返回第二个操作数;</li>
<li>第二个操作数是对象,则第一个操作数返回true,才返回第二个操作数,否则返回false;</li>
<li>有一个操作数是null,则返回null;</li>
<li>有一个操作数是undefined,则返回undefined。</li>
</ol>
<font style="background:#eee">总结上面几点就是:与运算符在运算时,如果第一个数在转换成布尔值的情况下是false则返回第一个操作数(原值,不一定是布尔值),否则返回第二个操作数</font>
<table>
<tbody>
<tr>
<td>*逻辑或</td>
<td> </td>
<td>:*</td>
</tr>
</tbody>
</table>
<p>如果两边的操作数有一个操作数不是布尔值的情况下,逻辑与运算就不一定返回布尔值,此时,遵循已下规则:</p>
<ol>
<li>第一个操作数是对象,则返回第一个操作数;</li>
<li>第一个操作数的求值结果为false,则返回第二个操作数;</li>
<li>两个操作数都是对象,则返回第一个操作数;</li>
<li>两个操作数都是null,则返回null;</li>
<li>两个操作数都是NaN,则返回NaN;</li>
<li>两个操作数都是undefined,则返回undefined;</li>
</ol>
<font style="background:#eee">总结上面几点就是:或运算符在运算时,如果第一个数在转换成布尔值的情况下是true则返回第一个操作数(原值,不一定是布尔值),否则返回第二个操作数</font>
<p><em>逻辑非!:</em></p>
<p>逻辑非运算符可以用于任何值。无论这个值是什么数据类型,这个运算符都会返回一个布尔值。它的流程是:先将这个值转换成布尔值,然后取反。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">!</span><span class="p">(</span><span class="mi">5</span> <span class="o">></span> <span class="mi">4</span><span class="p">);</span> <span class="c1">//false</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">!</span><span class="p">{};</span> <span class="c1">//false</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">!</span><span class="dl">''</span><span class="p">;</span> <span class="c1">//true</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">!</span><span class="mi">0</span><span class="p">;</span> <span class="c1">//true</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">!</span><span class="kc">null</span><span class="p">;</span> <span class="c1">//true</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">!</span><span class="kc">NaN</span><span class="p">;</span> <span class="c1">//true</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">!</span><span class="kc">undefined</span><span class="p">;</span> <span class="c1">//true</span>
</code></pre></div></div>
javascript笔记--(第四章)数据类型
2017-06-26T11:02:22+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/26/javascript笔记--(第四章)数据类型
<h2 id="数据类型">数据类型</h2>
<p>ECMAScript中有5种简单数据类型:Undefined、Null、Boolean、Number和String。还有一种复杂数据类型——Object。ECMAScript不支持任何创建自定义类型的机制,所有值都成为以上6中数据类型之一。</p>
<h2 id="typeof操作符">typeof操作符</h2>
<p>typeof操作符是用来检测变量的数据类型。对于值或变量使用typeof操作符会返回如下字符串。</p>
<ul>
<li>undefined - 如果变量是 Undefined 类型的</li>
<li>boolean - 如果变量是 Boolean 类型的</li>
<li>number - 如果变量是 Number 类型的</li>
<li>string - 如果变量是 String 类型的</li>
<li>object - 如果变量是一种引用类型或 Null 类型的</li>
</ul>
<p>function - 如果变量是函数(函数对象,Function是最顶层的构造器,Object也是一个函数对象,Object是被Function构造出来的。)</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">a</span><span class="p">);</span><span class="c1">//undefined</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">b</span><span class="p">);</span><span class="c1">//boolean</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">c</span><span class="p">);</span><span class="c1">//number</span>
<span class="kd">var</span> <span class="nx">d</span> <span class="o">=</span> <span class="dl">""</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">d</span><span class="p">);</span><span class="c1">//string</span>
<span class="kd">var</span> <span class="nx">e</span> <span class="o">=</span> <span class="p">{};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">e</span><span class="p">);</span><span class="c1">//object</span>
<span class="kd">var</span> <span class="nx">f</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">f</span><span class="p">);</span><span class="c1">//function</span>
</code></pre></div></div>
<p>注意:js只存在5种基本类型和一种引用类型。typeof返回的字符串并不代表类型,而是根据ECMScript标准来返回字符串,以下就是ECMScript对typeof操作符返回值的说明。</p>
<table summary="typeof Operator" style="font-size: 14px; font-family: Simsun; background-color: rgb(240, 240, 240);">
<thead style="background-color: silver;">
<tr style="border: 1px solid black;">
<th style="border: 1px solid black;">
Type
</th>
<th style="border: 1px solid black;">
<em>Result</em>
</th>
</tr>
</thead>
<tbody>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">
Undefined
</td>
<td style="border: 1px solid black;">
<strong><tt>"undefined"</tt></strong>
</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">
Null
</td>
<td style="border: 1px solid black;">
<strong><tt>"object"</tt></strong>
</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">
Boolean
</td>
<td style="border: 1px solid black;">
<strong><tt>"boolean"</tt></strong>
</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">
Number
</td>
<td style="border: 1px solid black;">
<strong><tt>"number"</tt></strong>
</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">
String
</td>
<td style="border: 1px solid black;">
<strong><tt>"string"</tt></strong>
</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">
Object (native and doesn't implement <a target="_blank" href="http://interglacial.com/javascript_spec/a-13.html#a-13.2.1" style="color: rgb(51, 102, 153); text-decoration: none;">[[Call]]</a>)
</td>
<td style="border: 1px solid black;">
<strong><tt>"object"</tt></strong>
</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">
Object (native and implements <a target="_blank" href="http://interglacial.com/javascript_spec/a-13.html#a-13.2.1" style="color: rgb(51, 102, 153); text-decoration: none;">[[Call]]</a>)
</td>
<td style="border: 1px solid black;">
<strong><tt>"function"</tt></strong>
</td>
</tr>
<tr style="border: 1px solid black;">
<td style="border: 1px solid black;">
Object (host)
</td>
<td style="border: 1px solid black;">
Implementation-dependent<br />
</td>
</tr>
</tbody>
</table>
<h2 id="undefined类型">Undefined类型</h2>
<p>Undefined类型只有一个值,即特殊的undefined。在使用var声明变量,但没有对其初始化时,这个变量的值就是undefined。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">a</span><span class="p">);</span><span class="c1">//undefined</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">);</span><span class="c1">//s报错</span>
</code></pre></div></div>
<p>注意:未初始化的变量和未定义的变量是不一样的。</p>
<h2 id="null类型">Null类型</h2>
<p>Null类型是一个只有一个值的数据类型,即特殊的值null。它表示一个空对象引用(指针),而typeof操作符检测null会返回object。undefined是派生自null的,因此ECMA-262规定对它们的相等性测试返回true。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
var a;
console.log(a==null);//true
console.log(a===null);//false
</script>
</code></pre></div></div>
<h2 id="boolean类型">Boolean类型</h2>
<p>虽然Boolean类型的字面量只有true和false两种,但ECMAScript中所有类型的值都有与这两个Boolean值等价的值。要将一个值转换为其对应的Boolean值,可以使用转型函数Boolean()。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">hello</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Hello World!</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">hello2</span> <span class="o">=</span> <span class="nb">Boolean</span><span class="p">(</span><span class="nx">hello</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="k">typeof</span> <span class="nx">hello2</span><span class="p">);</span><span class="c1">//boolean</span>
</code></pre></div></div>
<p>隐式转换:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">hello</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Hello World!</span><span class="dl">'</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">hello</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">如果条件为true,就执行我这条!</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">如果条件为false,就执行我这条!</span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
</code></pre></div></div>
<p>当要转换的值是至少有一个字符的字符串、非 0 数字或对象时,Boolean() 函数将返回 true。如果该值是空字符串、数字 0、NaN、undefined 或 null,它将返回 false。</p>
<p>可以用下面的代码测试 Boolean 型的强制类型转换:</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">b1</span> <span class="o">=</span> <span class="nb">Boolean</span><span class="p">(</span><span class="dl">""</span><span class="p">);</span> <span class="c1">//false - 空字符串</span>
<span class="kd">var</span> <span class="nx">b1</span> <span class="o">=</span> <span class="nb">Boolean</span><span class="p">(</span><span class="dl">"</span><span class="s2">hello</span><span class="dl">"</span><span class="p">);</span> <span class="c1">//true - 非空字符串</span>
<span class="kd">var</span> <span class="nx">b1</span> <span class="o">=</span> <span class="nb">Boolean</span><span class="p">(</span><span class="mi">50</span><span class="p">);</span> <span class="c1">//true - 非零数字</span>
<span class="kd">var</span> <span class="nx">b1</span> <span class="o">=</span> <span class="nb">Boolean</span><span class="p">(</span><span class="kc">null</span><span class="p">);</span> <span class="c1">//false - null</span>
<span class="kd">var</span> <span class="nx">b1</span> <span class="o">=</span> <span class="nb">Boolean</span><span class="p">(</span><span class="mi">0</span><span class="p">);</span> <span class="c1">//false - 零</span>
<span class="kd">var</span> <span class="nx">b1</span> <span class="o">=</span> <span class="nb">Boolean</span><span class="p">(</span><span class="k">new</span> <span class="nx">object</span><span class="p">());</span> <span class="c1">//true - 对象</span>
<span class="kd">var</span> <span class="nx">b1</span> <span class="o">=</span> <span class="nb">Boolean</span><span class="p">(</span><span class="kc">undefined</span><span class="p">);</span> <span class="c1">//false- 未定义</span>
</code></pre></div></div>
<h2 id="number类型">Number类型</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span><span class="p">;</span> <span class="c1">//十进制整数</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">070</span><span class="p">;</span> <span class="c1">//八进制,56</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">079</span><span class="p">;</span> <span class="c1">//无效的八进制,自动解析为79</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">08</span><span class="p">;</span> <span class="c1">//无效的八进制,自动解析为8</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mh">0xA</span><span class="p">;</span> <span class="c1">//十六进制,10</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mh">0x1f</span><span class="p">;</span> <span class="c1">//十六进制,31</span>
</code></pre></div></div>
<p>浮点类型,就是该数值中必须包含一个小数点,并且小数点后面必须至少有一位数字。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mf">3.8</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mf">0.8</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="p">.</span><span class="mi">8</span><span class="p">;</span> <span class="c1">//有效,但不推荐此写法</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">8</span><span class="p">.;</span> <span class="c1">//小数点后面没有值,转换为8</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mf">12.0</span><span class="p">;</span> <span class="c1">//小数点后面是0,转成为12</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mf">4.12e9</span><span class="p">;</span> <span class="c1">//即4120000000</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mf">0.00000000412</span><span class="p">;</span> <span class="c1">//即4.12e-9</span>
</code></pre></div></div>
<p>虽然浮点数值的最高精度是17位小数,但算术运算中可能会丢失精度。由于这个因素,做判断的时候一定要考虑到这个问题(比如使用整型判断)。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="mf">0.1</span><span class="o">+</span><span class="mf">0.2</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">)</span><span class="c1">//0.30000000000000004</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="mf">0.3</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="o">==</span><span class="nx">b</span><span class="p">);</span><span class="c1">//false</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="mf">0.09999999999999999999999</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">c</span><span class="p">);</span><span class="c1">//0.1</span>
</code></pre></div></div>
<p>Number.MIN_VALUE //最小值
Number.MAX_VALUE //最大值
Number.POSITIVE_INFINITY //Infinity(正无穷)
Number.NEGATIVE_INFINITY //-Infinity(负无穷)</p>
<p>如果超过了浮点数值范围的最大值或最小值,那么就先出现Infinity(正无穷)或者-Infinity(负无穷)。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span><span class="nx">e1000</span><span class="p">;</span> <span class="c1">//超出范围,Infinity</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="o">-</span><span class="mi">100</span><span class="nx">e1000</span><span class="p">;</span> <span class="c1">//超出范围,-Infinity</span>
</code></pre></div></div>
<p>要想确定一个数值到底是否超过了规定范围,可以使用isFinite()函数。如果没有超过,返回true,超过了返回false。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">100</span><span class="nx">e1000</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">isFinite</span><span class="p">(</span><span class="nx">box</span><span class="p">));</span> <span class="c1">//false</span>
</code></pre></div></div>
<h3 id="nan">NaN:</h3>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">0</span> <span class="o">/</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//NaN</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">12</span> <span class="o">/</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//Infinity</span>
<span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">12</span> <span class="o">/</span> <span class="mi">0</span> <span class="o">*</span> <span class="mi">0</span><span class="p">;</span> <span class="c1">//NaN</span>
</code></pre></div></div>
<p>任何与NaN进行运算的结果均为NaN,NaN与自身不相等(NaN不与任何值相等)。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nb">Number</span><span class="p">.</span><span class="kc">NaN</span><span class="p">);</span> <span class="c1">//NaN</span>
<span class="nx">alert</span><span class="p">(</span><span class="kc">NaN</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span> <span class="c1">//NaN</span>
<span class="nx">alert</span><span class="p">(</span><span class="kc">NaN</span> <span class="o">==</span> <span class="kc">NaN</span><span class="p">)</span> <span class="c1">//false</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="kc">NaN</span><span class="p">));</span> <span class="c1">//true</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="mi">25</span><span class="p">));</span> <span class="c1">//false,25是一个数值</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="dl">'</span><span class="s1">25</span><span class="dl">'</span><span class="p">));</span> <span class="c1">//false,'25'是一个字符串数值,可以转成数值</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee</span><span class="dl">'</span><span class="p">));</span> <span class="c1">//true,'Lee'不能转换为数值</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="kc">true</span><span class="p">));</span> <span class="c1">//false true可以转成成1</span>
</code></pre></div></div>
<p>isNaN()函数也适用于对象。在调用isNaN()函数过程中,如果定义了valueOf方法,会调用valueOf()方法,然后确定返回值是否能够转换成数值。如果没有定义valueOf方法,则调用toString()方法,再测试返回值是否能够转换成数值。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">toString</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">123</span><span class="dl">'</span><span class="p">;</span>
<span class="p">},</span>
<span class="na">valueOf</span><span class="p">:</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">lisong</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="nx">box</span><span class="p">));</span> <span class="c1">//true</span>
<span class="nx">box</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">toString</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">123</span><span class="dl">'</span><span class="p">;</span>
<span class="p">},</span>
<span class="cm">/*valueOf:function(){
return 'lisong';
}*/</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="nx">box</span><span class="p">));</span> <span class="c1">//false</span>
<span class="nx">box</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">toString</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">},</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">isNaN</span><span class="p">(</span><span class="nx">box</span><span class="p">));</span> <span class="c1">//false</span>
</code></pre></div></div>
<p>有3个函数可以把非数值转换为数值:Number()、parseInt()和parseFloat()。Number()函数是转型函数,可以用于任何数据类型,而另外两个则专门用于把字符串转成数值。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="kc">true</span><span class="p">));</span><span class="c1">//1,Boolean类型的true和false分别转换成1和0</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="kc">null</span><span class="p">));</span><span class="c1">//0,空对象返回0</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="kc">undefined</span><span class="p">));</span><span class="c1">//NaN,undefined返回NaN</span>
</code></pre></div></div>
<p>1.只包含数值的字符串,会直接转成成十进制数值,如果包含前导0,即自动去掉。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="dl">'</span><span class="s1">456</span><span class="dl">'</span><span class="p">));</span><span class="c1">//456</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="dl">'</span><span class="s1">070</span><span class="dl">'</span><span class="p">));</span><span class="c1">//70</span>
</code></pre></div></div>
<p>2.只包含浮点数值的字符串,会直接转成浮点数值,如果包含前导和后导0,即自动去掉。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="dl">'</span><span class="s1">08.90</span><span class="dl">'</span><span class="p">));</span><span class="c1">//8.9</span>
</code></pre></div></div>
<p>3.如果字符串是空,那么直接转成成0。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="dl">""</span><span class="p">));</span> <span class="c1">//0</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">""</span><span class="p">));</span> <span class="c1">//NaN</span>
</code></pre></div></div>
<p>4.如果不是以上三种字符串类型,则返回NaN。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee123</span><span class="dl">'</span><span class="p">);</span><span class="c1">//NaN</span>
<span class="nx">alert</span><span class="p">(</span><span class="dl">'</span><span class="s1">123Lee</span><span class="dl">'</span><span class="p">);</span><span class="c1">//NaN</span>
</code></pre></div></div>
<p>注意:Number转换的字符串中不会自动去掉字母和其他和数字无关的符号</p>
<p>5.如果是对象,首先会调用valueOf()方法,然后确定返回值是否能够转换成数值。如果没有valueOf()方法,会调用toString(),然后确定返回值是否能够转换成数值。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">toString</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">123</span><span class="dl">'</span><span class="p">;</span>
<span class="p">},</span>
<span class="na">valueOf</span><span class="p">:</span><span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">lisong</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="nx">box</span><span class="p">));</span> <span class="c1">//NaN</span>
<span class="nx">box</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">toString</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">123</span><span class="dl">'</span><span class="p">;</span>
<span class="p">},</span>
<span class="cm">/*valueOf:function(){
return 'lisong';
}*/</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="nx">box</span><span class="p">));</span> <span class="c1">//123</span>
<span class="nx">box</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">toString</span> <span class="p">:</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">},</span>
<span class="p">};</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">Number</span><span class="p">(</span><span class="nx">box</span><span class="p">));</span> <span class="c1">//1</span>
</code></pre></div></div>
<h3 id="prseint">prseInt():</h3>
<p>由于Number()函数在转换字符串时比较复杂且不够合理,因此在处理整数的时候更常用的是parseInt()。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nx">parsetInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">456Lee</span><span class="dl">'</span><span class="p">));</span><span class="c1">//456,会返回整数部分</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">parsetInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">Lee456Lee</span><span class="dl">'</span><span class="p">));</span><span class="c1">//NaN,如果第一个不是数值,就返回NaN</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">12Lee56Lee</span><span class="dl">'</span><span class="p">));</span><span class="c1">//12,从第一数值开始取,到最后一个连续数值结束</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">56.12</span><span class="dl">'</span><span class="p">));</span><span class="c1">//56,小数点不是数值,会被去掉</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">''</span><span class="p">));</span><span class="c1">//NaN,空返回NaN</span>
</code></pre></div></div>
<p>parseInt()除了能够识别十进制数值,也可以识别八进制和十六进制。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">0xA</span><span class="dl">'</span><span class="p">));</span><span class="c1">//10,十六进制</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">070</span><span class="dl">'</span><span class="p">));</span><span class="c1">//56,八进制</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">0xALee</span><span class="dl">'</span><span class="p">));</span><span class="c1">//100,十六进制,Lee被自动过滤掉</span>
</code></pre></div></div>
<p>ECMAScript为parseInt()提供了第二个参数,用于解决各种进制的转换。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">0xAF</span><span class="dl">'</span><span class="p">));</span><span class="c1">//175,十六进制</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">AF</span><span class="dl">'</span><span class="p">,</span><span class="mi">16</span><span class="p">));</span><span class="c1">//175,第二参数指定十六进制,可以去掉0x前导</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">AF</span><span class="dl">'</span><span class="p">));</span><span class="c1">//NaN,理所当然</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">101010101</span><span class="dl">'</span><span class="p">,</span><span class="mi">2</span><span class="p">));</span><span class="c1">//314,二进制转换</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseInt</span><span class="p">(</span><span class="dl">'</span><span class="s1">70</span><span class="dl">'</span><span class="p">,</span><span class="mi">8</span><span class="p">))</span><span class="c1">//56,八进制转换</span>
</code></pre></div></div>
<h3 id="parsefloat">parseFloat():</h3>
<p>parseFloat()是用于浮点数值转换的,和parseInt()一样,从第一位解析到非浮点数值位置。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nx">alert</span><span class="p">(</span><span class="nb">parseFloat</span><span class="p">(</span><span class="dl">'</span><span class="s1">123Lee</span><span class="dl">'</span><span class="p">));</span><span class="c1">//123,去掉不是别的部分</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseFloat</span><span class="p">(</span><span class="dl">'</span><span class="s1">0xA</span><span class="dl">'</span><span class="p">));</span><span class="c1">//0,不认十六进制</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseFloat</span><span class="p">(</span><span class="dl">'</span><span class="s1">123.4.5</span><span class="dl">'</span><span class="p">));</span><span class="c1">//123.4,只认一个小数点</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseFloat</span><span class="p">(</span><span class="dl">'</span><span class="s1">0123.400</span><span class="dl">'</span><span class="p">));</span><span class="c1">//123.4,去掉前后导</span>
<span class="nx">alert</span><span class="p">(</span><span class="nb">parseFloat</span><span class="p">(</span><span class="dl">'</span><span class="s1">1.234e7</span><span class="dl">'</span><span class="p">));</span><span class="c1">//12340000,把科学技术法转成普通数值</span>
</code></pre></div></div>
<h2 id="string类型">String类型</h2>
<p>String类型用于表示由于零或多个16位Unicode字符组成的字符序列,即字符串。ECMAScript中的字符串是不可变的,也就是说,字符串一旦创建,它们的值就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含新值的字符串填充该变量。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="dl">'</span><span class="s1">Mr.</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">box</span> <span class="o">=</span> <span class="nx">box</span> <span class="o">+</span> <span class="dl">'</span><span class="s1"> Lee</span><span class="dl">'</span><span class="p">;</span>
</code></pre></div></div>
<p>toString()方法可以把值转换成字符串。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span><span class="c1">//11</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span><span class="c1">//2</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="p">.</span><span class="nx">toString</span><span class="p">()</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span><span class="c1">//true1</span>
</code></pre></div></div>
<p>toString()方法一般是不需要传参的,但在数值转成字符串的时候,可以传递进制参数。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="mi">10</span><span class="p">;</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toString</span><span class="p">());</span><span class="c1">//10,默认输出</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">2</span><span class="p">));</span><span class="c1">//1010,二进制输出</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">box</span><span class="p">.</span><span class="nx">toString</span><span class="p">(</span><span class="mi">16</span><span class="p">));</span><span class="c1">//a,十六进制输出</span>
</code></pre></div></div>
<p>如果值有toString()方法,则调用该方法并返回相应的结果;如果是null或者undefined,则返回”null”或者”undeinfed”。不过可以用String(),这个函数能够将任何类型的值转换为字符串。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">a</span> <span class="p">;</span>
<span class="c1">//console.log(a.toString());//报错</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">String</span><span class="p">(</span><span class="nx">a</span><span class="p">));</span><span class="c1">//undefined</span>
<span class="nx">a</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="c1">//console.log(a.toString());//报错</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nb">String</span><span class="p">(</span><span class="nx">a</span><span class="p">));</span><span class="c1">//null</span>
</code></pre></div></div>
<h2 id="object类型">Object类型</h2>
<p>ECMAScript中的对象其实就是一组数据和功能的集合。对象可以通过执行new操作符后跟要创建的对象类型的名称来创建。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">();</span>
</code></pre></div></div>
<p>Object()是对象构造,如果对象初始化时不需要传递参数,可以不用写括号,但这种方式我们是不推荐的。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">;</span>
</code></pre></div></div>
<p>Object()里可以任意传参,可以传数值、字符串、布尔值等。而且,还可以进行相应的计算。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">var</span> <span class="nx">a</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">;</span>
<span class="nx">a</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="mi">2</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">a</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span><span class="c1">//3</span>
<span class="kd">var</span> <span class="nx">b</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">b</span><span class="p">.</span><span class="nx">toString</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="mi">2</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">b</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span><span class="c1">//2</span>
<span class="kd">var</span> <span class="nx">c</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Object</span><span class="p">(</span><span class="mi">1</span><span class="p">);</span>
<span class="nx">c</span><span class="p">.</span><span class="nx">valueOf</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="mi">2</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">c</span><span class="o">+</span><span class="mi">1</span><span class="p">);</span><span class="c1">//3</span>
</code></pre></div></div>
<p>注意:如果给对象传递了参数,则相当于于给对象定义了valueOf函数,我们可以重新定义valueOf函数和toString函数,valueOf函数在计算的时候优先级高于toString函数</p>
javascript笔记--(第三章)javascript语法,关键字,保留字
2017-06-26T09:33:49+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/26/javascript笔记--(第三章)javascript语法,关键字,保留字
<h2 id="语法构成">语法构成</h2>
<h3 id="区分大小写">区分大小写</h3>
<p>ECMAScript中的一切,包括变量、函数名和操作符都是区分大小写的。例如:text和Text表示两种不同的变量。</p>
<h3 id="标识符">标识符</h3>
<p>所谓标识符,就是指变量、函数、属性的名字,或者函数的参数。标识符可以是下列格式规则组合起来的一或多个字符:</p>
<ol>
<li>第一字符必须是一个字母、下划线(_)或一个美元符号($)</li>
<li>其他字符可以是字母、下划线、美元符号或数字</li>
<li>不能把关键字、保留字、true、false和null作为标识符</li>
</ol>
<h3 id="注释">注释</h3>
<p>ECMAScript使用C风格的注释,包括单行注释和块级注释。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 单行注释</span>
<span class="cm">/*
* 这是一个多行
* 注释
*/</span>
</code></pre></div></div>
<h3 id="直接量字面量literal">直接量(字面量literal)</h3>
<p>所有直接量(字面量),就是程序中直接显示出来的数据值。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mi">100</span> <span class="c1">//数字字面量</span>
<span class="dl">'</span><span class="s1">李炎恢</span><span class="dl">'</span> <span class="c1">//字符串字面量</span>
<span class="kc">false</span> <span class="c1">//布尔字面量</span>
<span class="o">/</span><span class="nx">js</span><span class="o">/</span><span class="nx">gi</span> <span class="c1">//正则表达式字面量</span>
<span class="kc">null</span> <span class="c1">//对象字面量</span>
<span class="p">{</span><span class="nl">x</span><span class="p">:</span><span class="mi">1</span><span class="p">,</span> <span class="nx">y</span><span class="p">:</span><span class="mi">2</span><span class="p">}</span> <span class="c1">//对象字面量表达式</span>
<span class="p">[</span><span class="mi">1</span><span class="p">,</span><span class="mi">2</span><span class="p">,</span><span class="mi">3</span><span class="p">,</span><span class="mi">4</span><span class="p">,</span><span class="mi">5</span><span class="p">]</span> <span class="c1">//数组字面量表达式</span>
</code></pre></div></div>
<h3 id="关键字和保留字">关键字和保留字</h3>
<p>ECMAScript-262描述了一组具有特定用途的关键字,一般用于控制语句的开始或结束,或者用于执行特定的操作等。关键字也是语言保留的,不能用作标识符。</p>
<p><em>ECMAScript的全部关键字(为第五版新增):</em></p>
<p>break do instanceof typeof case else new var catch finally return void continue for switch while debugger* function this with default if throw delete in try </p>
<p><em>ECMA-262中的全部保留字(第三版):</em></p>
<p>abstract enum int short boolean export interface static byte extends long super char final native class
synchronized float package throws const goto private transient debugger implements protected volatile double
import public</p>
<h3 id="变量">变量</h3>
<p>ECMAScript的变量是松散类型的,所谓松散类型就是用来保存任何类型的数据</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">a</span><span class="p">;</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span><span class="c1">//undefined</span>
<span class="nx">如果未对变量初始化</span><span class="err">,</span><span class="nx">默认将为undefined</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">a</span><span class="p">);</span><span class="c1">//报错</span>
</code></pre></div></div>
<p>如果未定义就使用,将报错</p>
<p>重复的使用var声明一个变量,只不过是一个赋值操作,并不会报错。但这样的操作是比较二的,没有任何必要。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">box</span><span class="o">=</span> <span class="dl">'</span><span class="s1">hello</span><span class="dl">'</span><span class="p">;</span>
<span class="kd">var</span> <span class="nx">box</span><span class="o">=</span> <span class="dl">'</span><span class="s1">word</span><span class="dl">'</span><span class="p">;</span>
<span class="nx">其他的</span><span class="err">:</span>
<span class="nx">box</span><span class="o">=</span> <span class="dl">'</span><span class="s1">hehe</span><span class="dl">'</span><span class="p">;</span><span class="c1">//和作用域有关</span>
<span class="kd">var</span> <span class="nx">box</span><span class="o">=</span> <span class="dl">'</span><span class="s1">hehe</span><span class="dl">'</span><span class="p">,</span><span class="nx">age</span> <span class="o">=</span> <span class="mi">28</span><span class="p">,</span><span class="nx">height</span><span class="p">;</span><span class="c1">//可以在一行定义多个变量</span>
</code></pre></div></div>
javascript笔记--(第二章)使用javascript
2017-06-26T09:25:40+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/26/javascript笔记--(第二章)使用javascript
<h2 id="内嵌代码">内嵌代码</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
alert(' 欢迎来到 JavaScript 世界! ');
</script>
</code></pre></div></div>
<p>注意:如果你想弹出一个 </script> 标签的字符串,那么浏览器会误解成 JS 代码已经结束了。解决的方法,就是把字符串分成两个部分,通过连接符 ‘ + ’ 来连接。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
alert(' 欢迎来到 JavaScript 世界! ');
alert('</script>');
</script>
</code></pre></div></div>
<p>以上脚本会报错,不能运行,改成如下即可:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript">
alert(' 欢迎来到 JavaScript 世界! ');
alert('</scr'+'ipt>');
</script>
</code></pre></div></div>
<h2 id="引入外部文件">引入外部文件</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><script type="text/javascript" src="demo1.js"></script>
</code></pre></div></div>
<h2 id="不支持js的处理">不支持js的处理</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><noscript>
您没有启用javascript
</noscript>
</code></pre></div></div>
javascript笔记--(第一章)javascript概述
2017-06-26T09:20:35+00:00
https://blog.lisong.hn.cn/javascript%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0/2017/06/26/javascript笔记--(第一章)javascript概述
<h2 id="什么是-javascript">什么是 JavaScript</h2>
<p>JavaScript 是一种具有面向对象能力的、解释型的程序设计语言。更具体一点,它是基于对象和事件驱动并具有相对安全性的客户端脚本语言 。 因为他不需要在一个语言环境下运行 , 而只需要支持它的浏览器即可 。 它的主要目的是 , 验证发往服务器端的数据 、 增加 We b互动、加强用户体验度等。</p>
<h2 id="javascript-特点">JavaScript 特点</h2>
<ul>
<li>松散性
JavaScript是一种松散类型的语言,也就是说,它的变量不必具有一个明确的类型。</li>
<li>对象属性
JavaScript中的对象把属性名映射为任意的属性值。它的这种方式很像哈希表或关联数组,而不像 C 中的结构体或者 C++ 、 Java 中的对象。</li>
<li>继承机制
JavaScript 中的面向对象继承机制是基于原型的。</li>
</ul>
<h2 id="ecmascript-介绍">ECMAScript 介绍</h2>
<p>由 ECMAScript-262 定义的 ECMAScript 与 Web 浏览器没有依赖关系。 ECMAScript 定义的只是这门语言的基础,而在此基础之上可以构建更完善的脚本语言。我们常见的 We b浏览器只是 ECMAScript 实现可能的宿主环境之一,在浏览器里运行的javascript脚本语言实现了该规则。既然他不依赖于 Web 浏览器,那么他还在哪些环境中寄宿呢?比如: ActionScript 、ScriptEase 等 。 而他的组成部分有 : 语法 、 类型 、 语句 、 关键字 、 保留字 、 操作符 、 对象等 。 ECMAScript目前有四个版本(1,2,3,4,5),不同的浏览器,对其的支持程度是不一样的,现在浏览器基本上至少都支持第3版,我们学的javascript通常也是指javascript第三版。</p>
<h2 id="javascript-核心">JavaScript 核心</h2>
<p>虽然 JavaScript 和 ECMAScript 通常被人们用来表达相同的含义,但 JavaScript 的含义却 比 ECMA-26 2 中规定的要多得多 。 一个完整 的 JavaScrip t 应该由下列三个不同的部分组成 。</p>
<ul>
<li>核心 (ECMAScript)</li>
<li>文档对象模型 (DOM)</li>
<li>浏览器对象模型 (BOM)</li>
</ul>
<h2 id="文档对象模型dom">文档对象模型(DOM)</h2>
<p>文档对象模型 (DOM , Document Object Model) 是针对 XML 但经过扩展用于 HTML 的应用程序编程接口 (API , Application Programmingg Interface) 。DOM 有三个级别,每个级别都会新增很多内容模块和标准,不同的浏览器对其的支持程度有所不同。</p>
<h2 id="浏览器对象模型bom">浏览器对象模型(BOM)</h2>
<p>访问和操作浏览器窗口的浏览器对象模型 (BOM , Browser Object Model) 。开发人员使用 BOM 可以控制浏览器显示页面以外的部分 。 而 BOM 真正与众不同的地方 ( 也是经常会导致问题的地方 ) ,还是它作为 JavaScript 实现的一部分,至今仍没有相关的标准。</p>
JavaScript设计模式(链式编程)
2017-06-25T07:53:06+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/06/25/JavaScript设计模式(链式编程)
<blockquote>
<p>JavaScript中的链式编程比较简单,可以在对象方法里返回this对象来实现简单的链式编程,Jquery中就用到了这种编程模式。</p>
</blockquote>
<h2 id="简单链式编程">简单链式编程</h2>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Person</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="p">}</span>
<span class="nx">Person</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">eat</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">吃饭</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Person</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">shower</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">洗澡</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">Person</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">sleep</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">'</span><span class="s1">睡觉</span><span class="dl">'</span><span class="p">);</span>
<span class="k">return</span> <span class="k">this</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">man</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Person</span><span class="p">();</span>
<span class="nx">man</span><span class="p">.</span><span class="nx">eat</span><span class="p">().</span><span class="nx">shower</span><span class="p">().</span><span class="nx">sleep</span><span class="p">();</span>
</code></pre></div></div>
JavaScript设计模式(单体模式)
2017-06-25T07:12:22+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/06/25/JavaScript设计模式(单体模式)
<blockquote>
<p>所谓的单体模式即单例模式,单体模式是我们最常用到的一种模式。单体模式范围四种:简单单体,闭包单体,惰性单体,分支单体。</p>
</blockquote>
<h2 id="简单单体">简单单体</h2>
<p>简单单体即对象字面量,在使用中对象字面量只实例化一次。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">property</span><span class="p">:</span><span class="dl">'</span><span class="s1">属性</span><span class="dl">'</span><span class="p">,</span>
<span class="na">method</span><span class="p">:</span> <span class="kd">function</span><span class="p">(){}</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="闭包单体">闭包单体</h2>
<p>闭包单体拥有私有作用域,只返回对外接口。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">add</span><span class="p">(){</span>
<span class="nx">sum</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="kd">get</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">sum</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">addSum</span><span class="p">:</span> <span class="nx">add</span><span class="p">,</span>
<span class="na">getSum</span><span class="p">:</span> <span class="kd">get</span>
<span class="p">}</span>
<span class="p">})()</span>
<span class="nx">obj</span><span class="p">.</span><span class="nx">addSum</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">getSum</span><span class="p">());</span>
</code></pre></div></div>
<h2 id="惰性单体">惰性单体</h2>
<p>惰性单体和闭包单体有点类似,不过只在要使用时才实例化。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">init</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">sum</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kd">function</span> <span class="nx">add</span><span class="p">(){</span>
<span class="nx">sum</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="kd">get</span><span class="p">(){</span>
<span class="k">return</span> <span class="nx">sum</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="p">{</span>
<span class="na">addSum</span><span class="p">:</span> <span class="nx">add</span><span class="p">,</span>
<span class="na">getSum</span><span class="p">:</span> <span class="kd">get</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span><span class="p">{</span>
<span class="na">getInstance</span><span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">result</span><span class="p">)</span>
<span class="nx">result</span> <span class="o">=</span> <span class="nx">init</span><span class="p">();</span>
<span class="k">return</span> <span class="nx">result</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">})()</span>
<span class="kd">var</span> <span class="nx">result</span> <span class="o">=</span> <span class="nx">obj</span><span class="p">.</span><span class="nx">getInstance</span><span class="p">();</span>
<span class="nx">result</span><span class="p">.</span><span class="nx">addSum</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">result</span><span class="p">.</span><span class="nx">getSum</span><span class="p">());</span>
</code></pre></div></div>
<h2 id="分支单体">分支单体</h2>
<p>分支单体可以根据条件返回单体对象,可用于浏览器检测,根据不同的浏览器返回不同的对象,来实现浏览器兼容。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">obj1</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">run</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">您使用的是火狐</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//statement</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">obj2</span> <span class="o">=</span> <span class="p">{</span>
<span class="na">run</span> <span class="p">:</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">return</span> <span class="dl">'</span><span class="s1">您使用的不是火狐</span><span class="dl">'</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//statement</span>
<span class="p">}</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">navigator</span><span class="p">.</span><span class="nx">userAgent</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="dl">"</span><span class="s2">Firefox</span><span class="dl">"</span><span class="p">)</span> <span class="o">></span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="k">return</span> <span class="nx">obj1</span><span class="p">;</span>
<span class="p">}</span><span class="k">else</span><span class="p">{</span>
<span class="k">return</span> <span class="nx">obj2</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">})()</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">run</span><span class="p">());</span>
</code></pre></div></div>
JavaScript设计模式(接口模式)
2017-06-25T06:19:51+00:00
https://blog.lisong.hn.cn/javascript%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/2017/06/25/JavaScript设计模式(接口模式)
<blockquote>
<p>Interface是强类型面向对象语言中固有的特性,简单来说就是一个规范和契约,可以用来实现对象与对象之间的解耦。但是JavaScript里本身是没有这一特性的,不过可以利用JavaScript的灵活性模拟接口。</p>
</blockquote>
<p>JavaScript模拟接口的方式一共有三种:</p>
<ol>
<li>文档注释方式</li>
<li>属性检查方式</li>
<li>鸭式辩型法</li>
</ol>
<h2 id="文档注释方式">文档注释方式</h2>
<p>文档注释方式是最简单的一种方式,只是用注释来说明类应该实现哪些方法。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cm">/**
* interface Composite {
* function add(obj);
* function remove(obj);
* function uopdate(obj);
* }
*/</span>
<span class="c1">// CompositeImpl implements Composite</span>
<span class="kd">var</span> <span class="nx">CompositeImpl</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="p">};</span>
<span class="nx">CompositeImpl</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">add</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span>
<span class="c1">// do something ...</span>
<span class="p">}</span>
<span class="nx">CompositeImpl</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">remove</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span>
<span class="c1">// do something ...</span>
<span class="p">}</span>
<span class="nx">CompositeImpl</span><span class="p">.</span><span class="nx">prototype</span><span class="p">.</span><span class="nx">update</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span>
<span class="c1">// do something ...</span>
<span class="p">}</span>
</code></pre></div></div>
<h2 id="属性检测法">属性检测法</h2>
<p>这种方法较注释法更加严谨一些,可以检测对象是否显示的实现了接口。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">function</span> <span class="nx">checkImpl</span><span class="p">(</span><span class="nx">obj</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">1</span><span class="p">;</span> <span class="nx">i</span> <span class="o"><</span> <span class="nx">arguments</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">inter</span> <span class="o">=</span> <span class="nx">arguments</span><span class="p">[</span><span class="nx">i</span><span class="p">];</span>
<span class="kd">var</span> <span class="nx">flag</span> <span class="o">=</span> <span class="kc">false</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">j</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">j</span><span class="o"><</span><span class="nx">obj</span><span class="p">.</span><span class="nx">implementtInterfaces</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">j</span><span class="o">++</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="nx">obj</span><span class="p">.</span><span class="nx">implementtInterfaces</span><span class="p">[</span><span class="nx">j</span><span class="p">]</span><span class="o">==</span><span class="nx">inter</span><span class="p">){</span>
<span class="nx">flag</span> <span class="o">=</span> <span class="kc">true</span><span class="p">;</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">flag</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">ImpObject</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">implementtInterfaces</span> <span class="o">=</span> <span class="p">[</span><span class="dl">'</span><span class="s1">Interface1</span><span class="dl">'</span><span class="p">];</span>
<span class="p">}</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">checkImpl</span><span class="p">(</span><span class="k">new</span> <span class="nx">ImpObject</span><span class="p">(),</span><span class="dl">'</span><span class="s1">Interface1</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">Interface2</span><span class="dl">'</span><span class="p">));</span>
</code></pre></div></div>
<h2 id="鸭式辩型法">鸭式辩型法</h2>
<p>该方式是最常用也是最经典的一种方式,实现了完全面向对象,可以检测是否实现了接口的方法。</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">var</span> <span class="nx">Interface</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">name</span><span class="p">,</span><span class="nx">methods</span><span class="p">){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">name</span> <span class="o">=</span> <span class="nx">name</span><span class="p">;</span>
<span class="k">this</span><span class="p">.</span><span class="nx">methods</span> <span class="o">=</span> <span class="nx">methods</span>
<span class="p">}</span>
<span class="nx">Interface</span><span class="p">.</span><span class="nx">checkImplement</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span><span class="nx">inter</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kd">var</span> <span class="nx">i</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span> <span class="nx">i</span><span class="o"><</span><span class="nx">inter</span><span class="p">.</span><span class="nx">methods</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span> <span class="nx">i</span><span class="o">++</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">method</span> <span class="o">=</span> <span class="nx">inter</span><span class="p">.</span><span class="nx">methods</span><span class="p">[</span><span class="nx">i</span><span class="p">]</span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">obj</span><span class="p">[</span><span class="nx">method</span><span class="p">]</span> <span class="o">||</span> <span class="k">typeof</span> <span class="nx">obj</span><span class="p">[</span><span class="nx">method</span><span class="p">]</span> <span class="o">!=</span> <span class="dl">'</span><span class="s1">function</span><span class="dl">'</span><span class="p">)</span>
<span class="k">return</span> <span class="kc">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="kc">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">interface1</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Interface</span><span class="p">(</span><span class="dl">'</span><span class="s1">Interface1</span><span class="dl">'</span><span class="p">,[</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">remove</span><span class="dl">'</span><span class="p">]);</span>
<span class="kd">var</span> <span class="nx">interface2</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">Interface</span><span class="p">(</span><span class="dl">'</span><span class="s1">Interface2</span><span class="dl">'</span><span class="p">,[</span><span class="dl">'</span><span class="s1">add</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">remove</span><span class="dl">'</span><span class="p">,</span><span class="dl">'</span><span class="s1">update</span><span class="dl">'</span><span class="p">]);</span>
<span class="kd">var</span> <span class="nx">ImpInterface1</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){</span>
<span class="k">this</span><span class="p">.</span><span class="nx">add</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="k">this</span><span class="p">.</span><span class="nx">remove</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(){};</span>
<span class="p">}</span>
<span class="kd">var</span> <span class="nx">obj</span> <span class="o">=</span> <span class="k">new</span> <span class="nx">ImpInterface1</span><span class="p">();</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Interface</span><span class="p">.</span><span class="nx">checkImplement</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span><span class="nx">interface1</span><span class="p">));</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">Interface</span><span class="p">.</span><span class="nx">checkImplement</span><span class="p">(</span><span class="nx">obj</span><span class="p">,</span><span class="nx">interface2</span><span class="p">));</span>
</code></pre></div></div>
js异步-setTimeout
2017-06-20T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2017/06/20/js异步-setTimeout
<blockquote>
<p> js引擎是单线程的,可是浏览器却可以是多线程的,js引擎只是浏览器的一个线程而已。定时器计,网络请求,浏览器渲染等等…,都是由不同的线程去完成的。</p>
</blockquote>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-06-20-js异步-setTimeout-1.jpg" alt="这里写图片描述" />
<img src="https://wanls4583.github.io/images/posts/其他/2017-06-20-js异步-setTimeout-2.jpg" alt="这里写图片描述" /></p>
<p> js引擎单线程执行的,它是基于事件驱动的语言.它的执行顺序是遵循一个叫做事件队列的机制。从图中我们可以看出,浏览器有各种各样的线程,比如事件触发器,网络请求,定时器等等.线程的联系都是基于事件的。js引擎处理到与其他线程相关的代码,就会分发给其他线程,他们处理完之后,需要js引擎计算时就是在事件队列里面添加一个任务。 这个过程中,js并不会阻塞代码等待其他线程执行完毕,而且其他线程执行完毕后添加事件任务告诉js引擎执行相关操作。这就是js的异步编程模型。</p>
<p>示例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">xmlns=</span><span class="s">"http://www.w3.org/1999/xhtml"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">http-equiv=</span><span class="s">"Content-Type"</span> <span class="na">content=</span><span class="s">"text/html; charset=utf-8"</span><span class="nt">/></span>
<span class="nt"><title></span>定时器<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nb">window</span><span class="p">.</span><span class="nx">onload</span> <span class="o">=</span> <span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">setTimeout_2</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">());</span>
<span class="p">},</span><span class="mi">100</span><span class="p">);</span>
<span class="nx">sleep</span><span class="p">(</span><span class="mi">100</span><span class="p">);</span>
<span class="nx">testNext</span><span class="p">();</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">testNext</span><span class="p">()</span> <span class="p">{</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">后续执行的函数</span><span class="dl">"</span><span class="p">);</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">sleep</span><span class="p">(</span><span class="nx">number</span><span class="p">)</span> <span class="p">{</span>
<span class="kd">var</span> <span class="nx">now</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">();</span>
<span class="kd">var</span> <span class="nx">exitTime</span> <span class="o">=</span> <span class="nx">now</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">+</span> <span class="nx">number</span><span class="p">;</span>
<span class="k">while</span> <span class="p">(</span><span class="kc">true</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">now</span> <span class="o">=</span> <span class="k">new</span> <span class="nb">Date</span><span class="p">();</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">now</span><span class="p">.</span><span class="nx">getTime</span><span class="p">()</span> <span class="o">></span> <span class="nx">exitTime</span><span class="p">)</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="nx">setTimeout</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">setTimeout_1</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="k">new</span> <span class="nb">Date</span><span class="p">().</span><span class="nx">getTime</span><span class="p">());</span>
<span class="p">},</span><span class="mi">0</span><span class="p">)</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>结果:
<img src="https://wanls4583.github.io/images/posts/其他/2017-06-20-js异步-setTimeout-3.jpg" alt="这里写图片描述" /></p>
<p>此时如果将sleep中的参数改小一点:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code>setTimeout(function(){
console.log("setTimeout_2");
console.log(2,new Date().getTime());
},100);
sleep(90);
testNext();
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-06-20-js异步-setTimeout-4.jpg" alt="这里写图片描述" /></p>
<p> 可以看到第一个定时器我们指定延时是100,第二个定时器指定的延时是0,但是通过设置循环的执行时间,可以改变他们两个的执行顺序(实际上是改变浏览器把他们加入到队列的顺序)。因为定时器setTimeout是由浏览器定时器模块来调度的,和js单线程是无关的,可以认为定时器模块有一个统一的时间,js执行setTimeout函数的时候,会传递延时参数和回调函数以及其他参数给定时器模块。浏览器定时器模块统一管理这些定时器。这些定时器开始的时间也即setTimeout执行时浏览器定时器模块的时间,当某个定时器的时间到了,浏览器定时器模块就会在任务列表末尾插入一个任务来执行相应的回调函数。</p>
<p>有一点需要注意的是:
js的dom跟新操作其实是异步的,当js操作dom元素需要跟新页面的显示时,将会在队列末尾插入一个页面跟新事件,当js执行到任务队列里的这个任务时就会去调用GUI引擎渲染页面。之所以这样,是因为js语言设定js引擎与GUI引擎是互斥的,js引擎在运行的时候会阻塞GUI引擎的渲染,GUI引擎在渲染的时候同样会阻塞js引擎的运行。另外,GUI的渲染频率一般是60帧,也就是1000/60毫秒渲染一次,如果同一个dom元素在此间隔内执行了多余一次相同性质的跟新操作,GUI引擎渲染的时候将只渲染最后一次的更新操作,也就是所谓的丢帧。</p>
<p>关于settimeout(0):
不同浏览器的实现情况不同,HTML5定义的最小时间间隔是4毫秒,使用settimeout(0)会使用浏览器支持的最小时间间隔。所以当我们需要把一些操作放到下一帧处理的时候,我们通常使用settimeout(0)来hack。</p>
前端性能优化之-css阻塞渲染
2017-05-30T22:23:00+00:00
https://blog.lisong.hn.cn/2017/05/30/前端性能优化之-css阻塞渲染
<blockquote>
<p> 为了防止页面重复渲染页面,降低浏览器性能,浏览器在CSSDOM构建完成之前,不会渲染页面,直观的感受就是,在css下载完成之前,浏览器将出现白屏现象。</p>
</blockquote>
<p><strong>浏览器渲染流程:</strong></p>
<ol>
<li>
<p>浏览器开始解析目标HTML文件,执行流的顺序为自上而下。</p>
</li>
<li>
<p>HTML解析器将HTML结构转换为基础的DOM(文档对象模型),构建DOM树完成后,触发DomContendLoaded事件。</p>
</li>
<li>
<p>CSS解析器将CSS解析为CSSOM(层叠样式表对象模型),一棵仅含有样式信息的树。</p>
</li>
<li>
<p>CSSOM和DOM开始合并构成渲染树,每个节点开始包含具体的样式信息。</p>
</li>
<li>
<p>计算渲染树中个各个节点的位置信息,即布局阶段。</p>
</li>
<li>
<p>将布局后的渲染树显示到界面上。</p>
</li>
</ol>
<p> 根据以上的流程,可以知道,当cssdom还没构建完成时,页面是不会渲染到浏览器界面的,这也是为什么当css下载过慢时,会出现白屏的现象,以下是模拟白屏的例子:</p>
<p>index.html:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>this is a test<span class="nt"></h1></span>
<span class="nt"><link</span> <span class="na">rel=</span><span class="s">"stylesheet"</span> <span class="na">type=</span><span class="s">"text/css"</span> <span class="na">href=</span><span class="s">"test.css"</span><span class="nt">></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"1.jpg"</span><span class="nt">></span>
<span class="nt"><hr></span>
<span class="nt"><span></span>this is a test<span class="nt"></span></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>test.css:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">img</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">50%</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>使用fidder延迟css的响应:</p>
<div class="language-js highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="nx">oSession</span><span class="p">.</span><span class="nx">uriContains</span><span class="p">(</span><span class="dl">'</span><span class="s1">test.css</span><span class="dl">'</span><span class="p">)){</span>
<span class="nx">oSession</span><span class="p">[</span><span class="dl">"</span><span class="s2">response-trickle-delay</span><span class="dl">"</span><span class="p">]</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">3000</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/前端优化/2017-05-30-前端性能优化之-css阻塞渲染-1.jpg" alt="这里写图片描述" /></p>
<p> 可以看到,在1.4s的时候,html文档和img已经下载完成,但是页面并没有渲染,而是等到css加载完成后再渲染出来,这也证实了css加载过程中会阻塞页面的渲染。所以在我们的前端日常开发中,应尽量减少css的响应时间。</p>
position自适应布局
2017-05-26T22:27:27+00:00
https://blog.lisong.hn.cn/css/2017/05/26/position自适应布局
<blockquote>
<p>position绝对布局时,left,right,top,bottom可以同时起作用,从而撑开元素。</p>
</blockquote>
<p>示例:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>position<span class="nt"></title></span>
<span class="nt"><style></span>
<span class="nc">.out</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">relative</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.inner1</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">50px</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.inner2</span><span class="p">{</span>
<span class="nl">position</span><span class="p">:</span> <span class="nb">absolute</span><span class="p">;</span>
<span class="nl">top</span><span class="p">:</span> <span class="m">50px</span><span class="p">;</span>
<span class="nl">bottom</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">left</span><span class="p">:</span> <span class="m">0px</span><span class="p">;</span>
<span class="nl">right</span><span class="p">:</span> <span class="m">0px</span><span class="p">;</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">green</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"out"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"inner1"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"inner2"</span><span class="nt">></div></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2018-05-26-position自适应布局-1.jpg" alt="这里写图片描述" /></p>
\r\n,\n,\r的历史及在不同系统下的区别
2017-04-26T09:58:16+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2017/04/26/rn,n,r的历史及在不同系统下的区别
<h2 id="回车与换行的历史由来">“回车”与”换行”的历史由来</h2>
<p> 在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。</p>
<p> 于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,比喻打印头定位在左边界;另一个叫做“换行”,比喻打字机把纸向下移一行,在打印的时候丢失的这两个标记字符正好可以拟补打印机的缺陷,这样就能避免丢失有效字符了。这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。</p>
<p> 后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。Unix系统里,每行结尾只有“<换行>”,即“\n”;Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;Mac系统里,每行结尾是“<回车>”,即“\r”。一个直接后果是,Unix/Mac系统下的文件在Windows里打开的话,所有文字会变成一行;而Windows里的文件在Unix/Mac下打开的话,在每行的结尾可能会多出一个符号^M(在Unix下多出一个\r,在Mac下多出一个\n)。</回车></换行></回车></换行></p>
<p>window下,编辑文件</p>
<p>1.txt:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2018-04-26-rn,n,r的历史及在不同系统下的区别-1.jpg" alt="这里写图片描述" /></p>
<p>用16进制编辑器打开:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2018-04-26-rn,n,r的历史及在不同系统下的区别-2.jpg" alt="这里写图片描述" /></p>
<p>可以看到,生成了1(32)和1之间插入了\r(0d)\n(0a)</p>
<p>不过在window下,用浏览器运行以下页面:</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="kd">function</span> <span class="nx">test</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">t</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="dl">"</span><span class="s2">textarea</span><span class="dl">"</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">value</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span><span class="c1">//3</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\r\n</span><span class="sr">/mg</span><span class="p">,</span><span class="dl">''</span><span class="p">).</span><span class="nx">length</span><span class="p">);</span><span class="c1">//3</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\n</span><span class="sr">/mg</span><span class="p">,</span><span class="dl">''</span><span class="p">).</span><span class="nx">length</span><span class="p">);</span><span class="c1">//2</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">t</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\r</span><span class="sr">/mg</span><span class="p">,</span><span class="dl">''</span><span class="p">).</span><span class="nx">length</span><span class="p">);</span><span class="c1">//3</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="dl">"</span><span class="s2">-----------------------</span><span class="dl">"</span><span class="p">)</span>
<span class="kd">var</span> <span class="nx">span</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementsByTagName</span><span class="p">(</span><span class="dl">"</span><span class="s2">span</span><span class="dl">"</span><span class="p">)[</span><span class="mi">0</span><span class="p">].</span><span class="nx">innerHTML</span><span class="p">;</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">span</span><span class="p">.</span><span class="nx">length</span><span class="p">);</span><span class="c1">//3</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">span</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\r\n</span><span class="sr">/mg</span><span class="p">,</span><span class="dl">''</span><span class="p">).</span><span class="nx">length</span><span class="p">);</span><span class="c1">//3</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">span</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\n</span><span class="sr">/mg</span><span class="p">,</span><span class="dl">''</span><span class="p">).</span><span class="nx">length</span><span class="p">);</span><span class="c1">//2</span>
<span class="nx">console</span><span class="p">.</span><span class="nx">log</span><span class="p">(</span><span class="nx">span</span><span class="p">.</span><span class="nx">replace</span><span class="p">(</span><span class="sr">/</span><span class="se">\r</span><span class="sr">/mg</span><span class="p">,</span><span class="dl">''</span><span class="p">).</span><span class="nx">length</span><span class="p">);</span><span class="c1">//3</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><textarea</span> <span class="na">onchange=</span><span class="s">"test();"</span><span class="nt">></textarea></span>
<span class="nt"><span></span>1
2<span class="nt"></span></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>得到的效果是这样的:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2018-04-26-rn,n,r的历史及在不同系统下的区别-3.jpg" alt="这里写图片描述" /></p>
<p>浏览器在解析处理的时候会自动把\r去掉。</p>
<p>最后,为了保险起见,我们编程的时候如果要匹配换行,最好三者都要匹配(<code class="language-plaintext highlighter-rouge">\r\n|\r|\r</code>)。</p>
git merge原理
2017-04-24T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/04/24/git merge原理
<h2 id="快照">快照</h2>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-04-24-git merge原理-1.jpg" alt="" /></p>
<p>这是项目的三个版本,版本1中有两个文件A和B,然后修改了A,变成了A1,形成了版本2,接着又修改了B变为B1,形成了版本3。</p>
<p>如果我们把项目的每个版本都保存到本地仓库,需要保存至少6个文件,而实际上,只有4个不同的文件,A、A1、B、B1。为了节省存储的空间,我们要想一个方法将同样的文件只需要保存一份。这就引入了Sha-1算法。</p>
<p>可以使用git命令计算文件的 sha-1 值:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s1">'test content'</span> | git hash-object <span class="nt">--stdin</span>
d670460b4b4aece5915caf5c68d12f560a9fe3e4
</code></pre></div></div>
<p>SHA-1将文件中的内容通过通过计算生成一个 40 位长度的hash值。
hash值相同,文件内容相同。因此,文件的sha-1值是可以作为文件的唯一 id。同时,它还有一个额外的功能,校验文件完整性。</p>
<p>有了 sha-1 的帮助,我们可以对项目版本的存储方式做一下调整。</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-04-24-git merge原理-2.jpg" alt="" /></p>
<h2 id="conflicts">Conflicts</h2>
<p>git 中的分支十分轻量,因此我们在使用git的时候会频繁的用到分支。不可不免的需要将新创建的分支合并。</p>
<p>在 git 中合并分支有两种选择:merge 和 rebase。但是,无论哪一种,都有可能产生冲突。因此我们先来看一下冲突的产生。</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-04-24-git merge原理-3.jpg" alt="" /></p>
<p>图上的情况,并不是移动分支指针就能解决问题的,它需要一种合并策略。首先,我们需要明确的是谁和谁的合并,是 <code class="language-plaintext highlighter-rouge">commit 2</code>,<code class="language-plaintext highlighter-rouge">commit 3</code> 与 <code class="language-plaintext highlighter-rouge">commit 4</code>,<code class="language-plaintext highlighter-rouge">commit 5</code>,<code class="language-plaintext highlighter-rouge">commit 6</code>的合并吗?说到分支,我们总会联想到线,就会认为是线的合并。其实不是的,真实合并的是 <code class="language-plaintext highlighter-rouge">3</code> 和 <code class="language-plaintext highlighter-rouge">6</code>。因为每一次提交都包含了项目完整的快照,即合并只是 tree 与 tree 的合并。</p>
<p>我们可以先想一个简单的算法。用来比较<code class="language-plaintext highlighter-rouge">commit 3</code>和<code class="language-plaintext highlighter-rouge">commit 6</code>。但是我们还需要一个比较的标准,如果只是<code class="language-plaintext highlighter-rouge">commit 3</code>和<code class="language-plaintext highlighter-rouge">commit 6</code>比较,那么<code class="language-plaintext highlighter-rouge">commit 3</code>与<code class="language-plaintext highlighter-rouge">commit 6</code>相比,添加了一个文件,也可以说成是<code class="language-plaintext highlighter-rouge">commit 6</code>与<code class="language-plaintext highlighter-rouge">commit 3</code>比删除了一个文件,这无法确切表示当前的冲突状态。因此我们选取他们的两个分支的分歧点(merge base)作为参考点,进行比较。</p>
<p>比较时,相对于 merge base(提交1)进行比较。</p>
<p>首先把<code class="language-plaintext highlighter-rouge">commit 1</code>、<code class="language-plaintext highlighter-rouge">commit 3</code>、<code class="language-plaintext highlighter-rouge">commit 6</code>中所有的文件做一个列表,然后依次遍历这个列表中的文件。现在我们拿列表中的一个文件进行举例,把在提交<code class="language-plaintext highlighter-rouge">commit 1</code>、<code class="language-plaintext highlighter-rouge">commit 3</code>、<code class="language-plaintext highlighter-rouge">commit 6</code>中的该文件分别称为<code class="language-plaintext highlighter-rouge">版本1</code>、<code class="language-plaintext highlighter-rouge">版本3</code>、<code class="language-plaintext highlighter-rouge">版本6</code>。</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">版本1</code>、<code class="language-plaintext highlighter-rouge">版本3</code>、<code class="language-plaintext highlighter-rouge">版本6</code>的 sha-1 值完全相同,这种情况表明没有冲突</li>
<li><code class="language-plaintext highlighter-rouge">版本3</code>或<code class="language-plaintext highlighter-rouge">版本6</code>至少一个与<code class="language-plaintext highlighter-rouge">版本1</code>状态相同(指的是sha-1值相同或都不存在),这种情况可以自动合并。比如<code class="language-plaintext highlighter-rouge">commit 1</code>中存在一个文件,在<code class="language-plaintext highlighter-rouge">commit 3</code>中没有对该文件进行修改,而<code class="language-plaintext highlighter-rouge">commit 6</code>中删除了这个文件,则以<code class="language-plaintext highlighter-rouge">commit 6</code>为准就可以了</li>
<li><code class="language-plaintext highlighter-rouge">版本3</code>或<code class="language-plaintext highlighter-rouge">版本6</code>都与<code class="language-plaintext highlighter-rouge">版本1</code>的状态不同,情况复杂一些,自动合并策略很难生效,需要手动解决。</li>
</ul>
<h2 id="实践">实践</h2>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-07-22-git常用命令-6.png" alt="" /></p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-07-22-git常用命令-7.png" alt="" /></p>
<p><code class="language-plaintext highlighter-rouge">git merge</code> 会产生一个新的提交:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-07-22-git常用命令-8.png" alt="" /></p>
实现微信内置浏览器全屏播放模式下html元素漂浮
2017-04-22T00:00:00+00:00
https://blog.lisong.hn.cn/%E7%A7%BB%E5%8A%A8%E7%AB%AF/2017/04/22/实现微信内置浏览器全屏播放模式下html元素漂浮
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"><meta</span> <span class="na">name=</span><span class="s">"viewport"</span> <span class="na">content=</span><span class="s">"width=device-width,user-scalable=no"</span><span class="nt">></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nt">html</span><span class="o">,</span><span class="nt">body</span> <span class="p">{</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100%</span><span class="p">;</span>
<span class="nl">-webkit-user-select</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="py">user-select</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">style=</span><span class="s">'position: fixed;z-index: 1;top:0px;left:0;width:40px;height: 40px;background-color: red'</span><span class="nt">></div></span>
<span class="nt"><video</span> <span class="na">height=</span><span class="s">"100%"</span> <span class="na">id=</span><span class="s">"mainvideo"</span> <span class="na">x5-video-player-type=</span><span class="s">"h5"</span> <span class="na">x5-video-player-fullscreen=</span><span class="s">"true"</span> <span class="na">x-webkit-airplay=</span><span class="s">"true"</span> <span class="na">playsinline</span> <span class="na">webkit-playsinline=</span><span class="s">"true"</span> <span class="na">src=</span><span class="s">"http://7xvl2z.com1.z0.glb.clouddn.com/nigg2.mp4"</span><span class="nt">></video></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>在微信内置浏览器下vedio标签调用的是微信内置的播放器,该播放器会全屏播放,此时html元素是不能漂浮在屏幕上的。<code class="language-plaintext highlighter-rouge">x5-video-player-fullscreen="true"</code>,<code class="language-plaintext highlighter-rouge">x5-video-player-type="h5"</code>两个属性可实现 andorid 微信内置浏览器中 vedio 调用 h5 内核的播放器来全屏播放,此时只剩一个返回按钮和一个分享按钮,并且html元素可浮动在视频上,效果如下:</p>
<p><img src="https://wanls4583.github.io/images/posts/移动端/2017-04-22-实现微信内置浏览器全屏播放模式下html元素漂浮-1.jpg" alt="这里写图片描述" /></p>
<p><code class="language-plaintext highlighter-rouge">playsinline</code>和<code class="language-plaintext highlighter-rouge">webkit-playsinline="true"</code>用来防止在 ios 下自动调用内置播放器全屏播放,改用内联播放模式。<code class="language-plaintext highlighter-rouge">x-webkit-airplay="true"</code>用来支持 Airplay 的设备(如:音箱、Apple TV)播放。</p>
bfc与margin折叠问题
2017-04-17T00:00:00+00:00
https://blog.lisong.hn.cn/css/2017/04/17/bfc与margin折叠问题
<blockquote>
<p>在解释BFC之前,先说一下文档流。我们常说的文档流其实分为定位流、浮动流和普通流三种。而普通流其实就是指BFC中的FC。FC是formatting context的首字母缩写,直译过来是格式化上下文,它是页面中的一块渲染区域,有一套渲染规则,决定了其子元素如何布局,以及和其他元素之间的关系和作用。常见的 FC 有 BFC、IFC,还有 GFC 和 FFC。BFC 是 block formatting context,也就是块级格式化上下文,是用于布局块级盒子的一块渲染区域。</p>
</blockquote>
<h2 id="bfc">BFC</h2>
<p>BFC是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面元素,反之亦然。它与普通的块框类似,但不同之处在于:</p>
<ul>
<li>可以阻止元素被浮动元素覆盖</li>
<li>可以包含浮动元素</li>
<li>属于同一个 BFC 的两个相邻块级子元素的上下 margin 会发生重叠。所以当两个相邻块级子元素分属于不同的BFC时可以阻止 margin 重叠</li>
</ul>
<h3 id="bfc-的形成">BFC 的形成:</h3>
<ul>
<li>根元素,即HTML元素</li>
<li>float的值不为none</li>
<li>overflow的值不为visible</li>
<li>display的值为inline-block、table-cell、table-caption</li>
<li>position的值为absolute或fixed</li>
</ul>
<h3 id="两列布局实现原理">两列布局实现原理:</h3>
<p>使左边框浮动(浮动形成 BFC),通过<code class="language-plaintext highlighter-rouge">overflow: hidden</code>使右边框形成 BFC,由于 BFC 之间不会重叠,迫使右边框宽度缩短,从而形成了两列布局的效果。</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Title<span class="nt"></title></span>
<span class="nt"><style></span>
<span class="nc">.main</span><span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.left</span><span class="p">{</span>
<span class="nl">float</span><span class="p">:</span> <span class="nb">left</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">200px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="nl">margin-right</span><span class="p">:</span> <span class="m">20px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.right</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">overflow</span><span class="p">:</span> <span class="nb">hidden</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">word-wrap</span><span class="p">:</span><span class="n">break-word</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"main"</span><span class="nt">></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"left"</span><span class="nt">></span>this is left<span class="nt"></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"right"</span><span class="nt">></span>this is right<span class="nt"></div></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><strong>结果:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/bfc-2.png" alt="" /></p>
<p>如果将右边框<code class="language-plaintext highlighter-rouge">overflow: hidden</code>去掉,将会发生重叠:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/bfc-3.png" alt="" /></p>
<h2 id="边距折叠">边距折叠</h2>
<ul>
<li>边距折叠只会发生在上下边距,左右边距是不会发生折叠的</li>
<li>边距折叠只发生邻接的上下边距中,也即兄弟节点或者父子节点</li>
<li>发生边距折叠的两个节点必须同处于一个bfc布局中</li>
<li>发生边距折叠的两个父子节点没有border或者padding隔开</li>
<li>只有普通文档流中块框的垂直外边距才会发生外边距合并,行内框、浮动框- 或绝对定位之间的外边距不会合并。</li>
</ul>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!DOCTYPE html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><meta</span> <span class="na">charset=</span><span class="s">"UTF-8"</span><span class="nt">></span>
<span class="nt"><title></span>Document<span class="nt"></title></span>
<span class="nt"><style </span><span class="na">type=</span><span class="s">"text/css"</span><span class="nt">></span>
<span class="nt">body</span><span class="p">{</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.d1</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">10px</span>
<span class="p">}</span>
<span class="nc">.d2</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="nl">display</span><span class="p">:</span> <span class="n">inline-block</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"d1"</span><span class="nt">></div></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"d2"</span><span class="nt">></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-17-bfc与margin折叠问题-1.jpg" alt="这里写图片描述" /></p>
<p>将行内块换成浮动块:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.d2</span><span class="p">{</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="nl">background</span><span class="p">:</span> <span class="no">blue</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">10px</span><span class="p">;</span>
<span class="nl">float</span><span class="p">:</span> <span class="nb">left</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-17-bfc与margin折叠问题-2.jpg" alt="这里写图片描述" /></p>
css3 动画之transition,animation
2017-04-16T00:00:00+00:00
https://blog.lisong.hn.cn/css/2017/04/16/css3 动画之transition,animation
<h2 id="css3动画">css3动画</h2>
<blockquote>
<p>csss3实现动画的方式主要有两种方式:一种是用transition过渡效果来实现动画,另外一种直接使用animation配合keyframe来实现。虽然这两种方式都能实现动画效果,但是区别还是有的。</p>
</blockquote>
<h3 id="transition">transition</h3>
<p>官方属性解释:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-1.jpg" alt="这里写图片描述" /></p>
<p>也可以把属性写成一行:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">div</span>
<span class="p">{</span>
<span class="nl">transition</span><span class="p">:</span> <span class="n">width</span> <span class="m">2s</span><span class="p">,</span> <span class="n">height</span> <span class="m">2s</span><span class="p">,</span> <span class="n">transform</span> <span class="m">2s</span><span class="p">;</span>
<span class="nl">-moz-transition</span><span class="p">:</span> <span class="n">width</span> <span class="m">2s</span><span class="p">,</span> <span class="n">height</span> <span class="m">2s</span><span class="p">,</span> <span class="n">-moz-transform</span> <span class="m">2s</span><span class="p">;</span>
<span class="nl">-webkit-transition</span><span class="p">:</span> <span class="n">width</span> <span class="m">2s</span><span class="p">,</span> <span class="n">height</span> <span class="m">2s</span><span class="p">,</span> <span class="n">-webkit-transform</span> <span class="m">2s</span><span class="p">;</span>
<span class="nl">-o-transition</span><span class="p">:</span> <span class="n">width</span> <span class="m">2s</span><span class="p">,</span> <span class="n">height</span> <span class="m">2s</span><span class="p">,</span><span class="n">-o-transform</span> <span class="m">2s</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p>transition主要用来实现两帧动画,也即开始和结束,通过过渡可以实现一些特殊的效果。transition动画既可以用鼠标hover状态来触发,也可以用js脚本来触发。</p>
<p>需要注意的是:transition默认有逆向动画的特性</p>
<h4 id="1hover触发">1.hover触发</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!doctype html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"><style></span>
<span class="nt">body</span><span class="o">,</span><span class="nt">html</span><span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">img</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span><span class="nb">absolute</span><span class="p">;</span>
<span class="nl">transition</span><span class="p">:</span> <span class="n">opacity</span> <span class="m">5s</span><span class="p">;</span>
<span class="nl">-webkit-transition</span><span class="p">:</span> <span class="n">opacity</span> <span class="m">5s</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.transparent</span> <span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.transparent</span><span class="nd">:hover</span><span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-1.jpg"</span> <span class="na">alt=</span><span class="s">"日景"</span><span class="nt">/></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-2.jpg"</span> <span class="na">alt=</span><span class="s">"夜景"</span> <span class="na">id=</span><span class="s">"nightImage"</span> <span class="na">class=</span><span class="s">"transparent"</span><span class="nt">/></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<iframe src="https://wanls4583.github.io/code/css/tansition-animation/test1.html" width="370" height="260" style="border-style: none"></iframe>
<p>当鼠标放上去后,夜景透明度将慢慢从0变成1,慢慢显示出来,因为夜景是在上层,所以日景将慢慢消失。因为transition动画默认有逆向动画的特性,当鼠标移开后,夜景将慢慢消失,日景将慢慢显示,而不是突兀的从夜景变为日景。</p>
<h4 id="2js脚本触发">2.js脚本触发</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!doctype html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"><style></span>
<span class="nt">body</span><span class="o">,</span><span class="nt">html</span><span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">img</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span><span class="nb">absolute</span><span class="p">;</span>
<span class="nl">transition</span><span class="p">:</span> <span class="n">opacity</span> <span class="m">5s</span><span class="p">;</span>
<span class="nl">-webkit-transition</span><span class="p">:</span> <span class="n">opacity</span> <span class="m">5s</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.solid</span> <span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.transparent</span> <span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"><script></span>
<span class="kd">function</span> <span class="nx">toNight</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">nightImage</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">nightImage</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">nightImage</span><span class="p">.</span><span class="nx">className</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">solid</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">toDay</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">nightImage</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">nightImage</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">nightImage</span><span class="p">.</span><span class="nx">className</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">transparent</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"toNight()"</span><span class="nt">></span>看夜景<span class="nt"></button></span>
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"toDay()"</span><span class="nt">></span>看日景<span class="nt"></button></span>
<span class="nt"><div></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-3.jpg"</span> <span class="na">alt=</span><span class="s">"日景"</span><span class="nt">/></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-4.jpg"</span> <span class="na">alt=</span><span class="s">"夜景"</span> <span class="na">id=</span><span class="s">"nightImage"</span> <span class="na">class=</span><span class="s">"transparent"</span><span class="nt">/></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<iframe src="https://wanls4583.github.io/code/css/tansition-animation/test2.html" width="370" height="300" style="border-style: none"></iframe>
<p>当点击看夜景后,夜景透明度将慢慢从0变成1,慢慢显示出来,因为夜景是在上层,所以日景将慢慢消失。因为transition动画默认有逆向动画的特性,当点击看日景将夜景图片的透明度改为0的时候,夜景并不会突兀的立马消失,而是随着透明度慢慢的从1变为0,慢慢的消失,日景也随之慢慢的显现出来。</p>
<h3 id="animation">animation</h3>
<p>@keyframes 规则和所有动画属性:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-2.jpg" alt="这里写图片描述" /></p>
<p>可以把所有属性写在一行:</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">div</span>
<span class="p">{</span>
<span class="nl">animation</span><span class="p">:</span> <span class="n">myfirst</span> <span class="m">5s</span> <span class="n">linear</span> <span class="m">2s</span> <span class="n">infinite</span> <span class="n">alternate</span> <span class="n">running</span><span class="p">;</span>
<span class="c">/* Firefox: */</span>
<span class="nl">-moz-animation</span><span class="p">:</span> <span class="n">myfirst</span> <span class="m">5s</span> <span class="n">linear</span> <span class="m">2s</span> <span class="n">infinite</span> <span class="n">alternate</span> <span class="n">running</span><span class="p">;</span>
<span class="c">/* Safari 和 Chrome: */</span>
<span class="nl">-webkit-animation</span><span class="p">:</span> <span class="n">myfirst</span> <span class="m">5s</span> <span class="n">linear</span> <span class="m">2s</span> <span class="n">infinite</span> <span class="n">alternate</span> <span class="n">running</span><span class="p">;</span>
<span class="c">/* Opera: */</span>
<span class="nl">-o-animation</span><span class="p">:</span> <span class="n">myfirst</span> <span class="m">5s</span> <span class="n">linear</span> <span class="m">2s</span> <span class="n">infinite</span> <span class="n">alternate</span> <span class="n">running</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<h3 id="keyframes有两种写法">keyframes有两种写法</h3>
<h4 id="1from和to">1.from和to</h4>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@keyframes</span> <span class="n">myfirst</span>
<span class="p">{</span>
<span class="nt">from</span> <span class="p">{</span><span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;}</span>
<span class="nt">to</span> <span class="p">{</span><span class="nl">background</span><span class="p">:</span> <span class="no">yellow</span><span class="p">;}</span>
<span class="p">}</span>
</code></pre></div></div>
<h4 id="2">2.%</h4>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">@keyframes</span> <span class="n">myfirst</span>
<span class="p">{</span>
<span class="err">0</span><span class="o">%</span> <span class="p">{</span><span class="nl">background</span><span class="p">:</span> <span class="no">red</span><span class="p">;}</span>
<span class="err">25</span><span class="o">%</span> <span class="p">{</span><span class="nl">background</span><span class="p">:</span> <span class="no">yellow</span><span class="p">;}</span>
<span class="err">50</span><span class="o">%</span> <span class="p">{</span><span class="nl">background</span><span class="p">:</span> <span class="no">blue</span><span class="p">;}</span>
<span class="err">100</span><span class="o">%</span> <span class="p">{</span><span class="nl">background</span><span class="p">:</span> <span class="no">green</span><span class="p">;}</span>
<span class="p">}</span>
</code></pre></div></div>
<p>animation主要用来实现多帧动画,多帧的状态是通过@keyframes来实现的,每个状态对应了一帧,在某些情况下元素的初始状态也是一帧。</p>
<p>需要注意的是:</p>
<ul>
<li>animation-direction默认状态下值为normal,即当动画到结束位置时不会自动逆向动画,会突然回到起点位置和状态,即使是循环动画,在运行到终点时也会突然回到起点位置和状态。当设置了值为alternate时,在动画到达终点时会沿着来时的动画轨迹逆向回到起点位置和状态(transition默认就有逆向动画的特性,可以想象成其也有个animation-direction属性,只不过只有个alternate值)。在设置了alternate的情况下,其逆向动画也算一次动画计数。</li>
<li>animation-play-state默认的值是running,也即运行状态,可以通过js代码使其为pause来暂停动画,当动画暂停时,动画的运行时间animation-duration也将暂停计时,当再次变为running值时,可以从当前位置继续运行动画。</li>
<li>animation-fill-mode默认值为none,也即当动画结束时会回到起点的位置和状态,可以将其设置为forwards,这样当动画结束后会保持在终点的位置和状态。</li>
</ul>
<h3 id="animation有三种方式触发">animation有三种方式触发</h3>
<h4 id="1直接给元素添加动画页面渲染时就触发">1.直接给元素添加动画,页面渲染时就触发</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!doctype html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"><style></span>
<span class="nt">body</span><span class="o">,</span><span class="nt">html</span><span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">div</span> <span class="p">{</span>
<span class="nl">background-color</span><span class="p">:</span> <span class="no">red</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">height</span><span class="p">:</span> <span class="m">100px</span><span class="p">;</span>
<span class="nl">animation</span><span class="p">:</span> <span class="n">myfirst</span> <span class="m">5s</span> <span class="n">forwards</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@keyframes</span> <span class="n">myfirst</span>
<span class="p">{</span>
<span class="err">100</span><span class="o">%</span><span class="p">{</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p>在这种情况下,元素的初始状态也是一帧,所以可以不用设置0%对应的状态</p>
<h4 id="2hover触发">2.hover触发</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!doctype html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"><style></span>
<span class="nt">body</span><span class="o">,</span><span class="nt">html</span><span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">img</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span><span class="nb">absolute</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.transparent</span> <span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.transparent</span><span class="nd">:hover</span><span class="p">{</span>
<span class="nl">animation</span><span class="p">:</span> <span class="n">night</span> <span class="m">5s</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@keyframes</span> <span class="n">night</span>
<span class="p">{</span>
<span class="err">100</span><span class="o">%</span><span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-5.jpg"</span> <span class="na">alt=</span><span class="s">"日景"</span><span class="nt">/></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-6.jpg"</span> <span class="na">alt=</span><span class="s">"夜景"</span> <span class="na">id=</span><span class="s">"nightImage"</span> <span class="na">class=</span><span class="s">"transparent"</span><span class="nt">/></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<iframe src="https://wanls4583.github.io/code/css/tansition-animation/test4.html" width="370" height="260" style="border-style: none"></iframe>
<p>这个效果和之前transition用hover触发的那个例子的效果一样,在用hover触发的情况下,动画的第一帧即元素当前所对应的状态,所以@keyframes night可以不设置0%的状态。</p>
<h4 id="3用js脚本触发">3.用js脚本触发</h4>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="cp"><!doctype html></span>
<span class="nt"><html</span> <span class="na">lang=</span><span class="s">"en"</span><span class="nt">></span>
<span class="nt"><head></span>
<span class="nt"><title></title></span>
<span class="nt"><style></span>
<span class="nt">body</span><span class="o">,</span><span class="nt">html</span><span class="p">{</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="nl">padding</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt">img</span> <span class="p">{</span>
<span class="nl">position</span><span class="p">:</span><span class="nb">absolute</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.transparent</span> <span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.day</span> <span class="p">{</span>
<span class="nl">animation</span><span class="p">:</span> <span class="n">day</span> <span class="m">5s</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.night</span> <span class="p">{</span>
<span class="nl">animation</span><span class="p">:</span> <span class="n">night</span> <span class="m">5s</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">@keyframes</span> <span class="n">night</span>
<span class="p">{</span>
<span class="err">0</span><span class="o">%</span><span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">100</span><span class="o">%</span><span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">@keyframes</span> <span class="n">day</span>
<span class="p">{</span>
<span class="err">0</span><span class="o">%</span><span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="err">100</span><span class="o">%</span><span class="p">{</span>
<span class="nl">opacity</span><span class="p">:</span> <span class="m">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"><script></span>
<span class="kd">function</span> <span class="nx">toNight</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">nightImage</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">nightImage</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">nightImage</span><span class="p">.</span><span class="nx">className</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">night</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
<span class="kd">function</span> <span class="nx">toDay</span><span class="p">(){</span>
<span class="kd">var</span> <span class="nx">nightImage</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="dl">"</span><span class="s2">nightImage</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">nightImage</span><span class="p">.</span><span class="nx">className</span> <span class="o">=</span> <span class="dl">"</span><span class="s2">day</span><span class="dl">"</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"toNight()"</span><span class="nt">></span>看夜景<span class="nt"></button></span>
<span class="nt"><button</span> <span class="na">onclick=</span><span class="s">"toDay()"</span><span class="nt">></span>看日景<span class="nt"></button></span>
<span class="nt"><div></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-7.jpg"</span> <span class="na">alt=</span><span class="s">"日景"</span><span class="nt">/></span>
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 动画之transition,animation-8.jpg"</span> <span class="na">alt=</span><span class="s">"夜景"</span> <span class="na">id=</span><span class="s">"nightImage"</span> <span class="na">class=</span><span class="s">"transparent"</span> <span class="nt">/></span>
<span class="nt"></div></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<iframe src="https://wanls4583.github.io/code/css/tansition-animation/test5.html" width="370" height="300" style="border-style: none"></iframe>
<p>这个例子的效果和之前transition用js触发的那个例子的效果一样,在用 js 事件改变 class 来触发 animation 动画的情况下,@keyframes 如果用百分号划分帧界限,则 @keyframes 默认的第一帧为规则里最小的那个值所对应的状态。如果用 from,to 划分,如果定义了 from,则为 from 所对应的状态,否则为 to。</p>
<p>在这个例子中,如果 @keyframes night 里没有0%的状态,则会突兀的把透明度变为1,而不会有过渡效果,因为其第一帧就是100%对应的那一帧。</p>
css3 3d转换之perspective,perspective-origin
2017-04-16T00:00:00+00:00
https://blog.lisong.hn.cn/css/2017/04/16/css3 3d转换之perspective,perspective-origin
<h2 id="perspective">perspective</h2>
<blockquote>
<p>perspective 属性对于3D变形来说至关重要。该属性会设置查看者的位置,并将可视内容映射到一个视锥上,继而投到一个2D视平面上。如果不指定透视,则Z轴空间中的所有点将平铺到同一个2D视平面中,并且变换结果中将不存在景深概念。</p>
</blockquote>
<p>以下为将图片沿x轴旋转一定角度的两个效果,一个设置了 perspective,一个没有设置 perspective,可以看到明显的区别。</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-1.jpg" alt="这里写图片描述" /></p>
<p>上面的描述可能让人难以理解一些,其实对于 perspective 属性,我们可以简单的理解为视距,用来设置用户和元素3D空间Z平面之间的距离。而其效应由他的值来决定,值越小,用户与3D空间Z平面距离越近,视觉效果更令人印象深刻;反之,值越大,用户与3D空间Z平面距离越远,视觉效果就很小。</p>
<p>为了加深印象,请看以下例子:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
.wrapper {
width: 50%;
float: left;
}
.cube {
font-size: 4em;
width: 2em;
margin: 1.5em auto;
transform-style: preserve-3d;
transform: rotateY(45deg);
}
.side {
position: absolute;
width: 2em;
height: 2em;
background: rgba(255, 99, 71, 0.6);
border: 1px solid rgba(0, 0, 0, 0.5);
color: white;
text-align: center;
line-height: 2em;
}
.front {
transform: translateZ(1em);
}
.top {
transform: rotateX(90deg) translateZ(1em);
}
.right{
transform: rotateY(90deg) translateZ(1em);
}
.left {
transform: rotateY(-90deg) translateZ(1em);
}
.bottom{
transform: rotateX(-90deg) translateZ(1em);
}
.back {
transform: rotateY(-180deg) translateZ(1em);
}
.w1 {
perspective: 1000px;
}
.w2{
perspective: 200px;
}
</style>
</head>
<body>
<div class="wrapper w1">
<div class="cube">
<div class="side front">1</div>
<div class="side back">6</div>
<div class="side right">4</div>
<div class="side left">3</div>
<div class="side top">5</div>
<div class="side bottom">2</div>
</div>
</div>
<div class="wrapper w2">
<div class="cube">
<div class="side front">1</div>
<div class="side back">6</div>
<div class="side right">4</div>
<div class="side left">3</div>
<div class="side top">5</div>
<div class="side bottom">2</div>
</div>
</div>
</body>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-2.jpg" alt="这里写图片描述" /></p>
<p>为了更好的理解 perspective 属性,我们很有必要把他和 translateZ 的关系结合起来。其实也可以把 perspective 的值简单的理解为人的眼睛到显示器的距离,而 translate 就是3D物体距离源点的距离,下面引用W3C的一张图来解说 perspective 和 translateZ 的关系。</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-3.jpg" alt="这里写图片描述" /></p>
<p>perspective 可以写在画布(父元素)上,也可以直接写在元素本身上,对于一张画布只有一个变型体的时候,几乎没有差别。但是当一个画布上有多个变型体的时候,两种写法的差别立即就表现出来了。就像下面这个例子,蓝色的部分,perspective 直接写在色块上,红色的部分,perspective 写在了父容器上,以画布作为透视元素,所以子元素的形态都是不一样的。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
body{
margin: 0;
padding: 50px 0 0 0;
}
.wrapper {
width: 45%;
float: left;
}
.w1 {
perspective: 1000px;
overflow: hidden;
border:2px solid red;
box-sizing: border-box;
margin-left: 2.5%;
}
.w2{
overflow: hidden;
border:2px solid blue;
box-sizing: border-box;
margin-left: 5%;
}
.block{
width: 100px;
height: 100px;
margin: 20px;
float: left;
transform: rotateY(45deg);
}
.w1 .block{
background-color: red;
}
.w2 .block{
transform: perspective(500px) rotateY(45deg);
background-color: blue;
}
</style>
</head>
<body>
<div class="wrapper w1">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
<div class="wrapper w2">
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
<div class="block"></div>
</div>
</body>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-4.jpg" alt="这里写图片描述" /></p>
<p>之所以会这样,是因为在父元素上设置了perspective后,所以子元素的源点都只有一个,默认为父元素的中心。而在子元素上设置 perspective,每个子元素都会有一个源点,所以表现行为都一样,关于源点,请看下面的 persepective-origin</p>
<p>perspective-origin</p>
<blockquote>
<p>perspective-origin属性是3D变形中另一个重要属性,主要用来决定perspective属性的源点角度。它实际上设置了X轴和Y轴位置(或者说基点),在该位置观看者好像在观看该元素的子元素。</p>
</blockquote>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt">perspective-origin</span><span class="o">:</span> <span class="nt">x-axis</span> <span class="nt">y-axis</span><span class="o">;</span>
</code></pre></div></div>
<p>x-axis:
定义视图在x轴上的位置。默认值:50%。可能的参数值形式:left、center、right、length和%。</p>
<p>y-axis:
定义视图在y轴上的位置。默认值:50%。可能的参数值形式:top、center、bottom、length和%。
看了上面的介绍可能还是不够清晰,没有能在大脑中形成一个清晰的概念,那么看下面这张图片:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-5.jpg" alt="这里写图片描述" /></p>
<p>下面这张截在W3C官网的图可以更好的阐述这一观点:</p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-6.jpg" alt="这里写图片描述" /></p>
<p>接下来看几个个例子:</p>
<p>下面的代码和上面的那个例子基本一样,只是改变了.w1,.w2,.cube三个css样式</p>
<h4 id="1源点向左偏">1.源点向左偏</h4>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.w1</span> <span class="p">{</span>
<span class="nl">perspective</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.w2</span><span class="p">{</span>
<span class="nl">perspective</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="nl">perspective-origin</span><span class="p">:</span> <span class="nb">left</span> <span class="nb">center</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.cube</span><span class="p">{</span>
<span class="nl">font-size</span><span class="p">:</span> <span class="m">4em</span><span class="p">;</span>
<span class="nl">width</span><span class="p">:</span> <span class="m">2em</span><span class="p">;</span>
<span class="nl">margin</span><span class="p">:</span> <span class="m">1.5em</span> <span class="nb">auto</span><span class="p">;</span>
<span class="nl">transform-style</span><span class="p">:</span> <span class="n">preserve-3d</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-7.jpg" alt="这里写图片描述" /></p>
<h4 id="2源点向上偏">2.源点向上偏</h4>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.w1</span> <span class="p">{</span>
<span class="nl">perspective</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.w2</span><span class="p">{</span>
<span class="nl">perspective</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="nl">perspective-origin</span><span class="p">:</span> <span class="nb">center</span> <span class="m">-100px</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-8.jpg" alt="这里写图片描述" /></p>
<p>3.源点向左偏的同时向上偏</p>
<div class="language-css highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">.w1</span> <span class="p">{</span>
<span class="nl">perspective</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="p">}</span>
<span class="nc">.w2</span><span class="p">{</span>
<span class="nl">perspective</span><span class="p">:</span> <span class="m">1000px</span><span class="p">;</span>
<span class="nl">perspective-origin</span><span class="p">:</span> <span class="nb">left</span> <span class="m">-100px</span><span class="p">;</span>
<span class="p">}</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-16-css3 3d转换之perspective,perspective-origin-9.jpg" alt="这里写图片描述" /></p>
<p>可以看到,我们只是给第二个盒子加了个 perspective-origin 属性,其表现结果却和第一个盒子有很大不同,这就是 perspective-origin 改变基点的作用。</p>
<p>参考:</p>
<p><a href="http://www.jb51.net/css/462429.html">http://www.jb51.net/css/462429.html</a></p>
fiddler断点命令
2017-04-13T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/04/13/fiddler断点命令
<p><strong>断点命令:</strong></p>
<ul>
<li><code class="language-plaintext highlighter-rouge">bpu</code>:在请求开始时中断</li>
<li><code class="language-plaintext highlighter-rouge">bpafter</code>:在响应到达时中断</li>
<li><code class="language-plaintext highlighter-rouge">bps</code>:在特定http状态码时中断</li>
<li><code class="language-plaintext highlighter-rouge">bpv/bpm</code>:在特定请求method时中断</li>
</ul>
<p>注意:以上所以命令在后面不加url的情况下表示清除断点过滤。</p>
<p>提示:命令输入区域输入help,回车执行会打开一页面详细介绍fiddler的所有命令。</p>
text-align实现两端对齐布局
2017-04-11T00:00:00+00:00
https://blog.lisong.hn.cn/css/2017/04/11/text-align实现两端对齐布局
<p><code class="language-plaintext highlighter-rouge">text-align:justify</code></p>
<p>该属性和值可实现文本两端对齐</p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">div</span>
<span class="p">{</span>
<span class="nl">border</span><span class="p">:</span><span class="m">1px</span> <span class="nb">solid</span> <span class="no">black</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><h1></span>CSS text-justify实例<span class="nt"></h1></span>
<span class="nt"><div></span>In my younger and more vulnerable years my father gave me some advice that I've been turning over in my mind ever since. 'Whenever you feel like criticizing anyone,' he told me, 'just remember that all the people in this world haven't had the advantages that you've had.'<span class="nt"></div></span>
<span class="nt"><p></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-1.jpg" alt="" /></p>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">div</span>
<span class="p">{</span>
<span class="nl">border</span><span class="p">:</span><span class="m">1px</span> <span class="nb">solid</span> <span class="no">black</span><span class="p">;</span>
<span class="nl">text-align</span><span class="p">:</span><span class="nb">justify</span>
<span class="p">}</span>
<span class="nt"></style></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-2.jpg" alt="" /></p>
<p>利用这个特性,结合<code class="language-plaintext highlighter-rouge">display:inline-block</code>可以实现两端对齐布局</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code><!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>菜鸟教程(runoob.com)</title>
<style>
.box{width:600px; padding:20px; margin:20px auto; background-color:#f0f3f9; text-align:justify;}
.list{width:120px; display:inline-block; padding-bottom:20px; text-align:center; vertical-align:top;}
.justify_fix{display:inline-block; width:100%; height:0; overflow:hidden;}/*使最后一行也可两端对齐*/
</style>
</head>
<body>
<div class="box">
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-1.jpg" />
哇哦,美女,口水,鼻血~~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-2.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-3.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-4.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-5.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-6.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-7.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-8.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-9.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="list"><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-10.jpg" />
哇哦,美女,口水,鼻血,不行了,我的小兔乱撞~~</span>
<span class="justify_fix"></span>
</div>
</body>
</html>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-text-align实现两端对齐布局-3.jpg" alt="" /></p>
css换行(white-space、word-wrap、word-break)
2017-04-11T00:00:00+00:00
https://blog.lisong.hn.cn/css/2017/04/11/css换行(white-space、word-wrap、word-break)
<h2 id="white-space">white-space</h2>
<table>
<thead>
<tr>
<th>值</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>normal</td>
<td>默认。空白会被浏览器忽略。</td>
</tr>
<tr>
<td>pre</td>
<td>空白会被浏览器保留。其行为方式类似 HTML 中的 <code class="language-plaintext highlighter-rouge"><pre></code> 标签。</td>
</tr>
<tr>
<td>nowrap</td>
<td>文本不会换行,文本会在在同一行上继续,直到遇到 <code class="language-plaintext highlighter-rouge"><br></code> 标签为止。</td>
</tr>
<tr>
<td>pre-wrap</td>
<td>保留空白符序列,但是正常地进行换行。</td>
</tr>
<tr>
<td>pre-line</td>
<td>合并空白符序列,但是保留换行符。</td>
</tr>
<tr>
<td>inherit</td>
<td>规定应该从父元素继承 <code class="language-plaintext highlighter-rouge">white-space</code> 属性的值。</td>
</tr>
</tbody>
</table>
<h3 id="pre">pre</h3>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">p</span><span class="nc">.test</span>
<span class="p">{</span>
<span class="nl">width</span><span class="p">:</span><span class="m">11em</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span><span class="m">1px</span> <span class="nb">solid</span> <span class="m">#000000</span><span class="p">;</span>
<span class="nl">white-space</span><span class="p">:</span><span class="n">pre</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><p</span> <span class="na">class=</span><span class="s">"test"</span><span class="nt">></span> This paragraph contains a word.
The long word will break and wrap to the next line.<span class="nt"></p></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-css换行(white-space、word-wrap、word-break)-1.jpg" alt="" /></p>
<h3 id="pre-line">pre-line</h3>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">p</span><span class="nc">.test</span>
<span class="p">{</span>
<span class="nl">width</span><span class="p">:</span><span class="m">11em</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span><span class="m">1px</span> <span class="nb">solid</span> <span class="m">#000000</span><span class="p">;</span>
<span class="nl">white-space</span><span class="p">:</span><span class="n">pre-line</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-css换行(white-space、word-wrap、word-break)-2.jpg" alt="" /></p>
<h3 id="pre-wrap">pre-wrap</h3>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">p</span><span class="nc">.test</span>
<span class="p">{</span>
<span class="nl">width</span><span class="p">:</span><span class="m">11em</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span><span class="m">1px</span> <span class="nb">solid</span> <span class="m">#000000</span><span class="p">;</span>
<span class="nl">white-space</span><span class="p">:</span><span class="n">pre-wrap</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-css换行(white-space、word-wrap、word-break)-3.jpg" alt="" /></p>
<h3 id="nowrap">nowrap</h3>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">p</span><span class="nc">.test</span>
<span class="p">{</span>
<span class="nl">width</span><span class="p">:</span><span class="m">11em</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span><span class="m">1px</span> <span class="nb">solid</span> <span class="m">#000000</span><span class="p">;</span>
<span class="nl">white-space</span><span class="p">:</span><span class="nb">nowrap</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-css换行(white-space、word-wrap、word-break)-4.jpg" alt="" /></p>
<h2 id="word-wrap">word-wrap</h2>
<table>
<thead>
<tr>
<th>值</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>normal</td>
<td>只在允许的断字点换行(浏览器保持默认处理)。</td>
</tr>
<tr>
<td>break-word</td>
<td>如果单词长度超过一行,允许在长单词或 URL 地址内部进行换行。</td>
</tr>
</tbody>
</table>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">p</span><span class="nc">.test</span>
<span class="p">{</span>
<span class="nl">width</span><span class="p">:</span><span class="m">11em</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span><span class="m">1px</span> <span class="nb">solid</span> <span class="m">#000000</span><span class="p">;</span>
<span class="nl">word-wrap</span><span class="p">:</span><span class="n">break-word</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><p</span> <span class="na">class=</span><span class="s">"test"</span><span class="nt">></span> This paragraph contains a very long word: thisisaveryveryveryveryveryverylongword. The long word will break and wrap to the next line.<span class="nt"></p></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-css换行(white-space、word-wrap、word-break)-5.jpg" alt="" /></p>
<h2 id="word-break">word-break</h2>
<table>
<thead>
<tr>
<th>值</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>normal</td>
<td>使用浏览器默认的换行规则。</td>
</tr>
<tr>
<td>break-all</td>
<td>允许在单词内换行。</td>
</tr>
<tr>
<td>keep-all</td>
<td>只能在半角空格或连字符处换行。</td>
</tr>
</tbody>
</table>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><style></span>
<span class="nt">p</span><span class="nc">.test</span>
<span class="p">{</span>
<span class="nl">width</span><span class="p">:</span><span class="m">11em</span><span class="p">;</span>
<span class="nl">border</span><span class="p">:</span><span class="m">1px</span> <span class="nb">solid</span> <span class="m">#000000</span><span class="p">;</span>
<span class="nl">word-break</span><span class="p">:</span><span class="n">break-all</span><span class="p">;</span>
<span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><p</span> <span class="na">class=</span><span class="s">"test"</span><span class="nt">></span> This paragraph contains a very long word: thisisaveryveryveryveryveryverylongword. The long word will break and wrap to the next line.<span class="nt"></p></span>
<span class="nt"></body></span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-04-11-css换行(white-space、word-wrap、word-break)-6.jpg" alt="" /></p>
<h2 id="word-wrap-与-word-break-的区别">word-wrap 与 word-break 的区别</h2>
<p><code class="language-plaintext highlighter-rouge">word-wrap:break-word</code>与<code class="language-plaintext highlighter-rouge">word-break:break-all</code>共同点是都能把长单词强行断句,不同点是<code class="language-plaintext highlighter-rouge">word-wrap:break-word</code>会首先起一个新行来放置长单词,新的行还是放不下这个长单词则会对长单词进行强制断句;而<code class="language-plaintext highlighter-rouge">word-break:break-all</code>则不会把长单词放在一个新行里,当这一行放不下的时候就直接强制断句了。</p>
line-height的底线、基线、中线、顶线
2017-03-28T00:00:00+00:00
https://blog.lisong.hn.cn/css/2017/03/28/line-height的底线、基线、中线、顶线
<p>说明:粉色为顶线,蓝色为中线(和英语本有点差异),绿色为基线,红色为底线</p>
<h3 id="vertical-aligntop"><code class="language-plaintext highlighter-rouge">vertical-align:top</code></h3>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-03-28-line-height的底线、基线、中线、顶线-1.jpg" alt="" /></p>
<h3 id="vertical-alignmiddle"><code class="language-plaintext highlighter-rouge">vertical-align:middle</code></h3>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-03-28-line-height的底线、基线、中线、顶线-2.jpg" alt="" /></p>
<h3 id="vertical-alignbaseline"><code class="language-plaintext highlighter-rouge">vertical-align:baseline</code></h3>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-03-28-line-height的底线、基线、中线、顶线-3.jpg" alt="" /></p>
<h3 id="vertical-alignbottom"><code class="language-plaintext highlighter-rouge">vertical-align:bottom</code></h3>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-03-28-line-height的底线、基线、中线、顶线-4.jpg" alt="" /></p>
<p><strong>结论:</strong></p>
<p>顶线和底线是相对于中线来计算的,当line-height为0时,顶线和底线将重合,而中线是相对于基线来计算的,基线始终在中线的下方(x的底部),vertical-algin:middle并不是对其到中线而是对齐到基线以上1/2x的位置。</p>
inline-block的基线问题
2017-03-28T00:00:00+00:00
https://blog.lisong.hn.cn/css/2017/03/28/inline-block的基线问题
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-03-28-inline-block的基线问题-1.jpg" alt="" /></p>
<p><img src="https://wanls4583.github.io/images/posts/CSS/2017-03-28-inline-block的基线问题-2.jpg" alt="" /></p>
<p>从测试结果可知:如果内联块里的没有文字,则其基线为margin-bottom的下边缘,如果有则为文字的基线</p>
git回退
2017-03-27T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/03/27/git回退
<h2 id="reset">reset</h2>
<p>git reset有三个可选项:</p>
<ul>
<li><code class="language-plaintext highlighter-rouge">--mixed</code>:默认,修改 HEAD,使其指向到对应版本号,并且清空暂存区(stage 或者叫 index),注意,这里的修改 HEAD 并不会改变工作区的文件。</li>
<li><code class="language-plaintext highlighter-rouge">--soft</code>:修改HEAD,使其指向到对应版本号,不会清空暂存区,也不会改变工作区的文件,并且会把当前版本相对于现在工作区有修改的文件添加到暂存区(添加到暂存区的文件和工作区的文件内容是一样,想要恢复对应版本号的文件,可以先<code class="language-plaintext highlighter-rouge">get reset HEAD</code>,然后<code class="language-plaintext highlighter-rouge">git checkout -- 'fileName/filePathName'</code>),此时可以直接提交。</li>
<li><code class="language-plaintext highlighter-rouge">--hard</code>:将文件恢复到对应版本号的状态,暂存区将被清空,工作区文件将被更改,恢复到对应版本号的状态。</li>
</ul>
<p><strong>git reset 也可回复单个文件或者单个文件夹</strong></p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git reset <span class="s1">'commitId'</span> <span class="s1">'fileName/filePathName'</span>
</code></pre></div></div>
<p>此时,并不会修改HEAD和工作区,也不会清空暂存区,只是会把对应版本号的文件放入暂存区,此时我们需要<code class="language-plaintext highlighter-rouge">git checkout -- 'fileName/filePathName'</code>即可恢复对应版本号的文件</p>
<h2 id="revert">revert</h2>
<p>revert 主要用来撤销某一次修改,如果之前提交增加了内容则会把该内容删除,如果之前提交删除了内容则会把相应内容恢复。</p>
<p>先假设我们有如下四次提交:</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-27日-git回退-1.jpg" alt="" /></p>
<p>bb15对应的内容为:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>test-revert-begin
</code></pre></div></div>
<p>c2a7对应的内容为:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>test-revert-begin
1
</code></pre></div></div>
<p>0869对已的内容为:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>test-revert-begin
2
</code></pre></div></div>
<p>此时我们想把c27a的修改撤销:</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-27日-git回退-2.jpg" alt="" /></p>
<p>会发现产生了冲突,此时打开1.txt:</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-27日-git回退-3.jpg" alt="" /></p>
<p>蓝色部分为撤销后的内容,红色内容为版本库最新的内容,发生了冲突,此时需要我们解决冲突后commit -am。</p>
<p><em>注意:如果我们revert<code class="language-plaintext highlighter-rouge">0869</code>,是不是产生冲突的,因为在<code class="language-plaintext highlighter-rouge">0869</code>之后没有再对 1.txt 进行过修改</em></p>
<h2 id="git-reset-与-git-revert-的区别">git reset 与 git revert 的区别</h2>
<p>reset 会删除指定版本之后的 commit,而 revert 会产生新的 commit,并且 revert 不可以回复单个文件</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-27日-git回退-4.jpg" alt="" /></p>
PS快捷键
2017-03-26T00:00:00+00:00
https://blog.lisong.hn.cn/ps/2017/03/26/PS快捷键
<p><strong>向下合并图层:</strong></p>
<p>Ctrl+E</p>
<p><strong>合并可见图层:</strong></p>
<p>Ctrl+Shift+E</p>
<p><strong>盖印图层:</strong></p>
<p>Ctrl+Shift+Alt+E</p>
<p><strong>自由变换:</strong></p>
<p>Ctrl+T</p>
<p><strong>快速选择菜单:</strong></p>
<p>Alt+相应菜单栏字母</p>
PS如何获取段落框的宽高
2017-03-26T00:00:00+00:00
https://blog.lisong.hn.cn/ps/2017/03/26/PS如何获取段落框的宽高
<p>可通过自由变换工具结合信息面板获取段落框的宽度和高度,快捷键Ctrl+T</p>
<p><img src="https://wanls4583.github.io/images/posts/PS/2017-03-26-PS如何获取段落框的宽高-1.jpg" alt="" /></p>
<p>X,Y 代表自由变换框左上角的相对于图像左上角的位置,W,H 代表自由变换框的宽度和高度</p>
PS切图
2017-03-26T00:00:00+00:00
https://blog.lisong.hn.cn/ps/2017/03/26/PS切图
<h2 id="传统切图">传统切图</h2>
<p>使用切片工具自己手动切图(类似裁剪),也可以基于参考线或者图层生成切图</p>
<h2 id="精准切图">精准切图</h2>
<p>使用菜单工具‘脚本->将图层到处到文件’。该命令可以把可见图层一个一个导出,导出到png格式可以选择裁切掉透明的区域,其他格式裁切的图层大小会和图像大小一样</p>
<p><img src="https://wanls4583.github.io/images/posts/PS/2017-03-26-PS切图-1.jpg" alt="" /></p>
<h2 id="自动切图">自动切图</h2>
<p>ps ccs 中可以开启自动生成器,更改相应图层的后缀,既可自动在目录下生成图片</p>
<h2 id="快速裁切">快速裁切</h2>
<p><strong>第一步:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/PS/2017-03-26-PS切图-2.jpg" alt="" /></p>
<p><strong>第二步:</strong></p>
<p><img src="https://wanls4583.github.io/images/posts/PS/2017-03-26-PS切图-3.jpg" alt="" /></p>
<p>勾选顶,左,底,右,则四周的相应像素会被裁剪掉,裁剪是针对全图像的,在一个图层上进行了该操作,整个图像会被裁切(其他图层也会被裁切)。</p>
apache配置
2017-03-18T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%85%B6%E4%BB%96/2017/03/18/apache配置
<h3 id="serverrroot">ServerrRoot:</h3>
<p>ServerRoot 用于指定守护进程httpd的运行目录,httpd 在启动之后将自动将进程的当前目录改变为这个目录,因此如果设置文件中指定的文件或目录是相对路径,那么真实路径就位于这个ServerR oot定义的路径之下。</p>
<h3 id="documentroot">DocumentRoot:</h3>
<p>服务器的web目录,用于存放web资源的目录</p>
<h3 id="options--indexes">Options -Indexes:</h3>
<p>阻止不存在 index.html 时候返回web目录文件列表,这里是-,如果是+则表示允许返回列表</p>
<h3 id="allowoverride">AllowOverride:</h3>
<p>指明 Apache 服务器是否去找<code class="language-plaintext highlighter-rouge">.htacess</code>文件作为配置文件,如果设置为<code class="language-plaintext highlighter-rouge">none</code>,那么服务器将忽略<code class="language-plaintext highlighter-rouge">.htacess</code>文件。</p>
<h3 id="htaccess">.htaccess:</h3>
<p><code class="language-plaintext highlighter-rouge">.htaccess</code>是一个纯文本文件,它里面存放着 Apache 服务器配置相关的指令。<code class="language-plaintext highlighter-rouge">.htaccess</code>主要的作用有:URL 重写、自定义错误页面、MIME 类型配置以及访问权限控制等。主要体现在伪静态的应用、图片防盗链、自定义404错误页面、阻止/允许特定 IP/IP 段、目录浏览与主页、禁止访问指定文件类型、文件密码保护等。
<code class="language-plaintext highlighter-rouge">.htaccess</code>的用途范围主要针对当前目录。</p>
<h3 id="directory权限配置">Directory权限配置:</h3>
<ul>
<li>Order allow,deny</li>
<li>deny 192.168</li>
<li>allow from all</li>
</ul>
<p><code class="language-plaintext highlighter-rouge">Order</code>用来指明<code class="language-plaintext highlighter-rouge">allow</code>和<code class="language-plaintext highlighter-rouge">deny</code>的顺序,上面的例子会先执行<code class="language-plaintext highlighter-rouge">allow from all</code> 在执行<code class="language-plaintext highlighter-rouge">deny 192.168</code></p>
<h3 id="followsymlinks">FollowSymLinks:</h3>
<p>允许使用符号链接</p>
<h3 id="symlinksifownermatch">SymLinksifOwnerMatch:</h3>
<p>如果那个链接目标文件的属主是当前运行apache程序的属主,就可以符号链接</p>
<h3 id="正向代理">正向代理:</h3>
<pre><code class="language-XML"><VirtualHost *:80>
DocumentRoot "D:/www/test"
ServerName www.test.com
<Directory "D:/www/test">
Options FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
#正向代理设置
ProxyRequests On#开启Apache正向代理
ProxyVia On#控制位于代理服务器链中的代理请求的流向
#用来控制谁可以访问你的代理
<Proxy *>
Order deny,allow
Deny from all
Allow from 127.0.0.1
</Proxy>
</VirtualHost>
</code></pre>
<p>如果在浏览器端设置了代理(以火狐为例):</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-03-18-apache配置-1.jpg" alt="" /></p>
<p>访问 <code class="language-plaintext highlighter-rouge">www.sina.com</code>,观察 HTTP 请求 Response:</p>
<p><img src="https://wanls4583.github.io/images/posts/其他/2017-03-18-apache配置-2.jpg" alt="" /></p>
<p>可以看到,<code class="language-plaintext highlighter-rouge">Via:www.test.com</code>,正向代理成功了。</p>
<h3 id="反向代理设置">反向代理设置:</h3>
<pre><code class="language-XML"><VirtualHost *:80>
DocumentRoot "D:/xampp/htdocs/lisong"
ServerName lisong.com
<Directory />
Options Indexes FollowSymLinks
AllowOverride All
Order allow,deny
Allow from all
</Directory>
#反向代理设置
ProxyPass /static http://www.xiazaiba.com/static
ProxyPassReverse /static http://www.xiazaiba.com/static
</VirtualHost>
</code></pre>
<div class="language-html highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nt"><html></span>
<span class="nt"><body></span>
lisong
<span class="nt"><img</span> <span class="na">src=</span><span class="s">"static/images/logo.png"</span><span class="nt">/></span>
<span class="nt"></body></span>
<span class="nt"></html></span>
</code></pre></div></div>
<h3 id="proxypassreverse-的作用">ProxyPassReverse 的作用:</h3>
<p>例如代理服务器的域名为<code class="language-plaintext highlighter-rouge">www.proxy.com</code>,客户端请求的域为<code class="language-plaintext highlighter-rouge">www.test.com</code>,当经过代理服务器处理完以后返回给客户端的是重定向到<code class="language-plaintext highlighter-rouge">www.proxy.com/ok.html</code>(也即发一个 Redirect 指令给客户端),如果配置了<code class="language-plaintext highlighter-rouge">ProxyPassReverse</code>,则会在发送<code class="language-plaintext highlighter-rouge">Redirect</code>指令到客户端之前将重定向地址改为<code class="language-plaintext highlighter-rouge">www.test.com/ok.html</code></p>
<p>参考:<a href="http://www.cnblogs.com/zemliu/archive/2012/04/18/2454655.html">http://www.cnblogs.com/zemliu/archive/2012/04/18/2454655.html</a></p>
git学习笔记
2017-03-15T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/03/15/git学习笔记
<h2 id="版本库">版本库</h2>
<p>工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。</p>
<p>Git 的版本库里存了很多东西,其中最重要的就是称为<code class="language-plaintext highlighter-rouge">stage</code>(或者叫<code class="language-plaintext highlighter-rouge">index</code>)的暂存区,还有 Git 为我们自动创建的第一个分支<code class="language-plaintext highlighter-rouge">master</code>,以及指向<code class="language-plaintext highlighter-rouge">master</code>的一个指针叫<code class="language-plaintext highlighter-rouge">HEAD</code>。</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-15-git学习笔记-1.jpg" alt="" /></p>
<p>注意事项:</p>
<ul>
<li><a href="https://wanls4583.github.io/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/2017/03/27/git%E5%9B%9E%E9%80%80/">版本回退</a>时可能会清空暂存区<code class="language-plaintext highlighter-rouge">stage</code>里的内容</li>
<li>用<code class="language-plaintext highlighter-rouge">git r</code>删除文件时,可以删除暂存区里的文件也可以删除版本库里的文件,不过删除版本库里的文件需要commit</li>
<li><code class="language-plaintext highlighter-rouge">git checkout -- file</code>可以把工作区的修改回退到仓库或者暂存区(如果 add 到暂存区了)</li>
</ul>
<h2 id="远程库">远程库</h2>
<p>可以从这个仓库克隆出新的仓库,也可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到 GitHub 仓库。本地库和远程库关联时,如果远程库里的文件在本地库里没有或者远程库的版本比本地的版本要新,则必须先<code class="language-plaintext highlighter-rouge">pull</code>才能<code class="language-plaintext highlighter-rouge">push</code>。如果是克隆下来的,则不需要再关联远程库。</p>
<h2 id="分支管理">分支管理</h2>
<p>创建和合并分支</p>
<p>当我们创建新的分支,例如<code class="language-plaintext highlighter-rouge">dev</code>,Git 新建一个指针叫<code class="language-plaintext highlighter-rouge">dev</code>,指向<code class="language-plaintext highlighter-rouge">master</code>相同的提交,再把<code class="language-plaintext highlighter-rouge">HEAD</code>指向<code class="language-plaintext highlighter-rouge">dev</code>,就表示当前分支在<code class="language-plaintext highlighter-rouge">dev</code>上。</p>
<p>Git创建一个分支很快,因为除了增加一个dev指针,改改HEAD的指向,工作区的文件都没有任何变化。</p>
<p>创建dev分支,然后切换到dev分支:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git checkout <span class="nt">-b</span> dev
Switched to a new branch <span class="s1">'dev'</span>
git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
<span class="nv">$ </span>git branch dev
<span class="nv">$ </span>git checkout dev
Switched to branch <span class="s1">'dev'</span>
</code></pre></div></div>
<p>然后,用git branch命令查看当前分支:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git branch
<span class="k">*</span> dev
master
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">git branch</code>命令会列出所有分支,当前分支前面会标一个*号。</p>
<p><code class="language-plaintext highlighter-rouge">dev</code>分支的工作完成,我们就可以切换回<code class="language-plaintext highlighter-rouge">master</code>分支了:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git checkout master
Switched to branch <span class="s1">'master'</span>
</code></pre></div></div>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-15-git学习笔记-2.jpg" alt="" /></p>
<p>然后,把dev分支的工作成果合并到master分支上:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git merge dev
Updating d17efd8..fec145a
Fast-forward
readme.txt | 1 +
1 file changed, 1 insertion<span class="o">(</span>+<span class="o">)</span>
</code></pre></div></div>
<p>git merge命令用于合并指定分支到当前分支。</p>
<p>注意到上面的<code class="language-plaintext highlighter-rouge">Fast-forward</code>信息,Git告诉我们,这次合并是“快进模式”,也就是直接把<code class="language-plaintext highlighter-rouge">master</code>指向<code class="language-plaintext highlighter-rouge">dev</code>的当前提交,所以合并速度非常快。</p>
<p>合并完成后,就可以放心地删除dev分支了:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git branch <span class="nt">-d</span> dev
Deleted branch dev <span class="o">(</span>was fec145a<span class="o">)</span><span class="nb">.</span>
</code></pre></div></div>
<p>删除后,查看branch,就只剩下master分支了:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git branch
<span class="k">*</span> master
</code></pre></div></div>
<p>因为创建、合并和删除分支非常快,所以 Git 鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在 master 分支上工作效果是一样的,但过程更安全。</p>
<p>合并dev分支时使用<code class="language-plaintext highlighter-rouge">--no-ff</code>参数,表示禁用<code class="language-plaintext highlighter-rouge">Fast forward</code>:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$ </span>git merge <span class="nt">--no-ff</span> <span class="nt">-m</span> <span class="s2">"merge with no-ff"</span> dev
Merge made by the <span class="s1">'recursive'</span> strategy.
readme.txt | 1 +
1 file changed, 1 insertion<span class="o">(</span>+<span class="o">)</span>
</code></pre></div></div>
<p>不使用<code class="language-plaintext highlighter-rouge">Fast forward</code>模式,merge后就像这样:</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-15-git学习笔记-3.jpg" alt="" /></p>
<p>相对于快速合并模式,该模式会生成一个记录<code class="language-plaintext highlighter-rouge">merge</code>操作的<code class="language-plaintext highlighter-rouge">commit id</code>,可以在<code class="language-plaintext highlighter-rouge">git log</code>里查看到。不过有一种情况比较特殊:如果在有冲突的情况下,这两种其实是没区别的,因为有冲突的情况下<code class="language-plaintext highlighter-rouge">git merge --no-ff -m 'xxx'</code>不能通过。</p>
<h2 id="合并冲突">合并冲突</h2>
<p>当在<code class="language-plaintext highlighter-rouge">master</code>和<code class="language-plaintext highlighter-rouge">dev</code>分支上都对同一文件进行了修改,则合并的时候可能产生冲突,此时不能再用快速合并,需要先手动修改,add后再提交。</p>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-15-git学习笔记-4.jpg" alt="" /></p>
<h2 id="删除分支">删除分支</h2>
<h4 id="普通删除">普通删除</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch <span class="nt">-d</span> dev
</code></pre></div></div>
<h4 id="强行删除">强行删除</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git branch <span class="nt">-D</span> dev
</code></pre></div></div>
<h2 id="stash">stash</h2>
<p><code class="language-plaintext highlighter-rouge">stash</code>可以将当前的工作区保存起来,当用<code class="language-plaintext highlighter-rouge">git stash apply</code>或者<code class="language-plaintext highlighter-rouge">git stash pop</code>返回现场时,会发生<code class="language-plaintext highlighter-rouge">merge</code>,如果文件有冲突,需要手动解决。</p>
<h2 id="多人协作">多人协作</h2>
<h4 id="查看远程库信息">查看远程库信息</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote <span class="nt">-v</span>
</code></pre></div></div>
<h4 id="推送信息到远程库">推送信息到远程库</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin master
git push origin dev
</code></pre></div></div>
<h4 id="关联本地分支与远程分支">关联本地分支与远程分支</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout <span class="nt">-b</span> dev
git pull origin dev
</code></pre></div></div>
<h4 id="在本地新建分支并推送到远程">在本地新建分支并推送到远程</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout <span class="nt">-b</span> <span class="nb">test
</span>git push origin <span class="nb">test</span> //这样远程仓库中也就创建了一个test分支
</code></pre></div></div>
<h4 id="克隆">克隆</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone git@github.com:michaelliao/learngit.git
</code></pre></div></div>
<h4 id="抓取分支">抓取分支</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout <span class="nt">-b</span> dev origin/dev
</code></pre></div></div>
<h2 id="标签">标签</h2>
<p>Git 的标签是版本库的快照,其实它就是指向某个commit的指针,跟分支很像,但是分支可以移动,标签不能移动。</p>
<h4 id="创建标签">创建标签</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git tag v0.1
git tag <span class="nt">-a</span> v0.1 <span class="nt">-m</span> <span class="s2">"version 0.1 released"</span>
</code></pre></div></div>
<h4 id="查看标签列表">查看标签列表</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git tag
</code></pre></div></div>
<h4 id="查看标签详情">查看标签详情</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git show v0.1
</code></pre></div></div>
<h4 id="删除标签">删除标签</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git tag <span class="nt">-d</span> v0.1
</code></pre></div></div>
<h4 id="删除远程标签">删除远程标签</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin :refs/tags/v0.1
</code></pre></div></div>
<h4 id="推送标签到远程库">推送标签到远程库</h4>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push origin v0.1
git push origin <span class="nt">--tags</span> //推送全部
</code></pre></div></div>
<h2 id="关于git的pull与push">关于git的pull与push</h2>
<ul>
<li>当本地有未<code class="language-plaintext highlighter-rouge">push</code>的<code class="language-plaintext highlighter-rouge">commit</code>,此时如果远程仓库的版本比本地的版本要新,<code class="language-plaintext highlighter-rouge">pull</code>时会发生<code class="language-plaintext highlighter-rouge">merge</code>,并针对此<code class="language-plaintext highlighter-rouge">merge</code>生成相应的<code class="language-plaintext highlighter-rouge">commitId</code>。</li>
<li>如果远程仓库的版本比本地的版本要新,此时<code class="language-plaintext highlighter-rouge">push</code>会失败,提示需要先<code class="language-plaintext highlighter-rouge">pull</code>。</li>
<li><code class="language-plaintext highlighter-rouge">commit</code>了一次以后,此时如果你没有<code class="language-plaintext highlighter-rouge">pull</code>,则会提示你<code class="language-plaintext highlighter-rouge">ahead of</code> ‘远程分支’ by 1 <code class="language-plaintext highlighter-rouge">commits</code>,但是如果你本地版本不是最新的,你<code class="language-plaintext highlighter-rouge">pull</code>以后会发生<code class="language-plaintext highlighter-rouge">merge</code>,该<code class="language-plaintext highlighter-rouge">merge</code>会生成相应的<code class="language-plaintext highlighter-rouge">commitId</code>,此时本地的<code class="language-plaintext highlighter-rouge">HEAD</code>是改<code class="language-plaintext highlighter-rouge">merge</code>的<code class="language-plaintext highlighter-rouge">commitId</code>,每<code class="language-plaintext highlighter-rouge">merge</code>一次,提示的超前版本数量会增加一。</li>
</ul>
<p><img src="https://wanls4583.github.io/images/posts/开发工具/2017-03-15-git学习笔记-5.jpg" alt="" /></p>
JAVA动态代理
2017-02-15T00:00:00+00:00
https://blog.lisong.hn.cn/java/2017/02/15/JAVA动态代理
<p>java JDK动态代理实现原理是用 JDK6 Complier API 实现的</p>
<p>示例:模仿 spring的AOP</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">InvocationHandler</span><span class="o">.</span><span class="na">java</span>
<span class="kn">package</span> <span class="nn">com.bjsxt.proxy</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.reflect.Method</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">interface</span> <span class="nc">InvocationHandler</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">invoke</span><span class="o">(</span><span class="nc">Object</span> <span class="n">o</span><span class="o">,</span> <span class="nc">Method</span> <span class="n">m</span><span class="o">);</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Proxy.java</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">com.bjsxt.proxy</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.File</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.FileWriter</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.reflect.Constructor</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.lang.reflect.Method</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.URL</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.URLClassLoader</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.tools.JavaCompiler</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.tools.StandardJavaFileManager</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.tools.ToolProvider</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">javax.tools.JavaCompiler.CompilationTask</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Proxy</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="nc">Object</span> <span class="nf">newProxyInstance</span><span class="o">(</span><span class="nc">Class</span> <span class="n">infce</span><span class="o">,</span> <span class="nc">InvocationHandler</span> <span class="n">h</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span> <span class="c1">//JDK6 Complier API, CGLib, ASM</span>
<span class="nc">String</span> <span class="n">methodStr</span> <span class="o">=</span> <span class="s">""</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">rt</span> <span class="o">=</span> <span class="s">"\r\n"</span><span class="o">;</span>
<span class="nc">Method</span><span class="o">[]</span> <span class="n">methods</span> <span class="o">=</span> <span class="n">infce</span><span class="o">.</span><span class="na">getMethods</span><span class="o">();</span>
<span class="k">for</span><span class="o">(</span><span class="nc">Method</span> <span class="n">m</span> <span class="o">:</span> <span class="n">methods</span><span class="o">)</span> <span class="o">{</span>
<span class="n">methodStr</span> <span class="o">+=</span> <span class="s">"@Override"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">"public void "</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="na">getName</span><span class="o">()</span> <span class="o">+</span> <span class="s">"() {"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">" try {"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">" Method md = "</span> <span class="o">+</span> <span class="n">infce</span><span class="o">.</span><span class="na">getName</span><span class="o">()</span> <span class="o">+</span> <span class="s">".class.getMethod(\""</span> <span class="o">+</span> <span class="n">m</span><span class="o">.</span><span class="na">getName</span><span class="o">()</span> <span class="o">+</span> <span class="s">"\");"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">" h.invoke(this, md);"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">" }catch(Exception e) {e.printStackTrace();}"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">"}"</span><span class="o">;</span>
<span class="o">}</span>
<span class="nc">String</span> <span class="n">src</span> <span class="o">=</span>
<span class="s">"package com.bjsxt.proxy;"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">"import java.lang.reflect.Method;"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">"public class $Proxy1 implements "</span> <span class="o">+</span> <span class="n">infce</span><span class="o">.</span><span class="na">getName</span><span class="o">()</span> <span class="o">+</span> <span class="s">"{"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">" public $Proxy1(InvocationHandler h) {"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">" this.h = h;"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">" }"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="s">" com.bjsxt.proxy.InvocationHandler h;"</span> <span class="o">+</span> <span class="n">rt</span> <span class="o">+</span>
<span class="n">methodStr</span> <span class="o">+</span>
<span class="s">"}"</span><span class="o">;</span>
<span class="nc">String</span> <span class="n">fileName</span> <span class="o">=</span>
<span class="s">"d:/src/com/bjsxt/proxy/$Proxy1.java"</span><span class="o">;</span>
<span class="nc">File</span> <span class="n">f</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">File</span><span class="o">(</span><span class="n">fileName</span><span class="o">);</span>
<span class="nc">FileWriter</span> <span class="n">fw</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">FileWriter</span><span class="o">(</span><span class="n">f</span><span class="o">);</span>
<span class="n">fw</span><span class="o">.</span><span class="na">write</span><span class="o">(</span><span class="n">src</span><span class="o">);</span>
<span class="n">fw</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span>
<span class="n">fw</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="c1">//compile</span>
<span class="nc">JavaCompiler</span> <span class="n">compiler</span> <span class="o">=</span> <span class="nc">ToolProvider</span><span class="o">.</span><span class="na">getSystemJavaCompiler</span><span class="o">();</span>
<span class="nc">StandardJavaFileManager</span> <span class="n">fileMgr</span> <span class="o">=</span> <span class="n">compiler</span><span class="o">.</span><span class="na">getStandardFileManager</span><span class="o">(</span><span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">);</span>
<span class="nc">Iterable</span> <span class="n">units</span> <span class="o">=</span> <span class="n">fileMgr</span><span class="o">.</span><span class="na">getJavaFileObjects</span><span class="o">(</span><span class="n">fileName</span><span class="o">);</span>
<span class="nc">CompilationTask</span> <span class="n">t</span> <span class="o">=</span> <span class="n">compiler</span><span class="o">.</span><span class="na">getTask</span><span class="o">(</span><span class="kc">null</span><span class="o">,</span> <span class="n">fileMgr</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="kc">null</span><span class="o">,</span> <span class="n">units</span><span class="o">);</span>
<span class="n">t</span><span class="o">.</span><span class="na">call</span><span class="o">();</span>
<span class="n">fileMgr</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="c1">//load into memory and create an instance</span>
<span class="no">URL</span><span class="o">[]</span> <span class="n">urls</span> <span class="o">=</span> <span class="k">new</span> <span class="no">URL</span><span class="o">[]</span> <span class="o">{</span><span class="k">new</span> <span class="no">URL</span><span class="o">(</span><span class="s">"file:/"</span> <span class="o">+</span> <span class="s">"d:/src/"</span><span class="o">)};</span>
<span class="nc">URLClassLoader</span> <span class="n">ul</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">URLClassLoader</span><span class="o">(</span><span class="n">urls</span><span class="o">);</span>
<span class="nc">Class</span> <span class="n">c</span> <span class="o">=</span> <span class="n">ul</span><span class="o">.</span><span class="na">loadClass</span><span class="o">(</span><span class="s">"com.bjsxt.proxy.$Proxy1"</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">c</span><span class="o">);</span>
<span class="nc">Constructor</span> <span class="n">ctr</span> <span class="o">=</span> <span class="n">c</span><span class="o">.</span><span class="na">getConstructor</span><span class="o">(</span><span class="nc">InvocationHandler</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="nc">Object</span> <span class="n">m</span> <span class="o">=</span> <span class="n">ctr</span><span class="o">.</span><span class="na">newInstance</span><span class="o">(</span><span class="n">h</span><span class="o">);</span>
<span class="c1">//m.move();</span>
<span class="k">return</span> <span class="n">m</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p><em>Proxy实现步骤:</em></p>
<ol>
<li>根据传过来的接口 Class,遍历其中的方法(拼接使用<code class="language-plaintext highlighter-rouge">InvocationHandler</code>调用方法的代码字符串),使用 IO 操作生成对应的 java 类文件</li>
<li>根据步骤1生成的 java 类文件,使用<code class="language-plaintext highlighter-rouge">JavaCompiler</code>类将其编程成 class</li>
<li>使用<code class="language-plaintext highlighter-rouge">URLClassLoader</code>将 class 载入内存,调用 class 的构造方法实例化对象</li>
</ol>
<p><em>使用:</em></p>
<p>Client.java</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">Client</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Exception</span> <span class="o">{</span>
<span class="nc">Tank</span> <span class="n">t</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Tank</span><span class="o">();</span>
<span class="nc">InvocationHandler</span> <span class="n">h</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TimeHandler</span><span class="o">(</span><span class="n">t</span><span class="o">);</span>
<span class="nc">Moveable</span> <span class="n">m</span> <span class="o">=</span> <span class="o">(</span><span class="nc">Moveable</span><span class="o">)</span><span class="nc">Proxy</span><span class="o">.</span><span class="na">newProxyInstance</span><span class="o">(</span><span class="nc">Moveable</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">h</span><span class="o">);</span>
<span class="n">m</span><span class="o">.</span><span class="na">move</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p><strong>CGLIB 和 JDK生成动态代理类</strong></p>
<p>区别:</p>
<ul>
<li>JDK 动态代理只能对实现了接口的类生成代理,而不能针对类 CGLIB 是针对类实现代理,其原理是通过字节码技术为一个类创建子类,主要是对指定的类生成一个子类,覆盖其中的方法,因为是继承,所以该类或方法最好不要声明成<code class="language-plaintext highlighter-rouge">final</code>。</li>
<li>springAOP 使用的设计模式就是动态代理模式。如果目标对象实现了接口,则 spring 使用 jdk 动态代理技术,如果目标对象没有实现接口,则 spring 使用 CGLIB 技术。</li>
</ul>
Angularjs双向数据绑定原理
2017-01-31T00:00:00+00:00
https://blog.lisong.hn.cn/%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6/2017/01/31/Angularjs双向数据绑定原理
<p>angular并不存在定时脏检测。angular 对常用的 dom 事件,xhr 事件等做了封装,在里面触发进入 angular 的<code class="language-plaintext highlighter-rouge">digest</code>流程。在<code class="language-plaintext highlighter-rouge">digest</code>流程里面,会从<code class="language-plaintext highlighter-rouge">rootscope</code>开始遍历,检查所有的<code class="language-plaintext highlighter-rouge">watcher</code>。</p>
<p>谈起angular的脏检查机制(<code class="language-plaintext highlighter-rouge">dirty-checking</code>), 常见的误解就是认为: ng 是定时轮询去检查 model 是否变更。
其实,ng 只有在指定事件触发后,才进入<code class="language-plaintext highlighter-rouge">$digest cycle</code>:</p>
<ul>
<li>angular 系统自带 DOM 事件,譬如用户输入文本,点击按钮等。(ng-click)</li>
<li>XHR 响应事件 (<code class="language-plaintext highlighter-rouge">$http</code>)</li>
<li>浏览器 Location 变更事件 (<code class="language-plaintext highlighter-rouge">$location</code>)</li>
<li>Timer 事件(<code class="language-plaintext highlighter-rouge">$timeout</code>, <code class="language-plaintext highlighter-rouge">$interval</code>)</li>
<li>执行<code class="language-plaintext highlighter-rouge">$digest()</code>或<code class="language-plaintext highlighter-rouge">$apply()</code></li>
</ul>