2020年10月19日 星期一

《面試官別再問》JavaScript 動態建立變數的方法,怎麼動態生成js變數

//簡單的用字串作為變數名

window['hello'] = "hello, world";

alert(hello);

//批量定義

for(var i=0; i<10; i++) {

var varname="var"+i;

window[varname] = "value"+i;

}

alert(var0);

alert(var9);


eval("var a=1");//宣告一個變數a並賦值1。

eval("2 3");//執行加運算,並返回運算值。

eval("mytest()");//執行mytest()函式。

eval("{b:2}");//宣告一個物件。


1、eval太神秘了,以至於很多人用錯。所以不推薦使用。

eval只是一個普通的函數,只不過他有一個快速通道通向編譯器,可以將string變成可執行的代碼。有類似功能的還有Function , setInterval和setTimeout。

2、 eval不容易調試。用chromeDev等調試工具無法打斷點調試,所以麻煩的東西也是不推薦使用的… 

3、說到性能問題,在舊的瀏覽器中如果你使用了eval,性能會下降10倍。在現代瀏覽器中有兩種編譯模式:fast path和slow path。fast path是編譯那些穩定和可預測(stable and predictable)的代碼。而明顯的,eval不可預測,所以將會使用slow path ,所以會慢。還有一個是,在使用類似於Closure Compiler等壓縮(混淆)代碼時,使用eval會報錯。(又慢又報錯,我還推薦嗎?)

4、關於安全性,我們經常聽到eval是魔鬼,他會引起XSS攻擊,實際上,如果我們對信息源有足夠的把握時,eval並不會引起很大的安全問題。而且不光是eval,其他方式也可能引起安全問題。比如:   莫名其妙給你注入一個<script src="">標籤,或者一段來歷不明的JSON-P請求,再或者就是Ajax請求中的eval代碼…   所以啊,只要你的信息源不安全,你的代碼就不安全。不單單是因為eval引起的。你用eval的時候會在意XSS的問題,你越在意就越出問題,出的多了,eval就成噩夢了。

5、效率問題是程序邏輯問題。對於一些有執行字符串代碼需求的程序中,不用eval而用其他方式模擬反而會帶來更大的開銷。

2020年7月24日 星期五

《面試官別再問》提高 Laravel 框架性能 PHP7 + Swoole + Stone

PHP每次的每次請求結束, 都會釋放掉執行中建立的所有資源。這樣有一個很大的好處:PHP程序員基本不用費力去考慮資源釋放的問題,諸如內存,IO句柄,數據庫連接等,請求結束時PHP將全部釋放。PHP程序員幾乎不用關心內存釋放的問題,也很難寫出內存泄露的程序。這讓PHP變得更加簡單容易上手, 直抒心意。但是也帶來了一個壞處:PHP很難在請求間復用資源, 類似PHP框架這種耗時的工作, 每次請求都需要反復做——即使每次都在做同樣的事情。也正因為如此,在PHP發展過程中,關於是否使用框架的爭論也從未停止過。

Stone主要優化的就是這個問題。 在框架資源初始化結束后再開啟一個FastCGI服務,這樣, 新的請求過來是直接從資源初始化結束后的狀態開始,避免每次請求去做資源初始化的事情。所以, 本質上, Stone運行時是常駐內存的,它和PHP-FPM一樣,是一個FastCGI的實現,不同的是, FPM每次執行請求都需要重新初始化框架, Stone直接使用初始化的結果。

同樣,事情總是有好有壞。壞處是:PHP編程變得更難了, 你需要考慮內存的釋放,需要關心PHP如何使用內存。甚至, 你需要了解使用的框架,以免『不小心』寫出讓人『驚喜』的效果。同時, PHP的調試變得更難, 因為每次修改程序后需要重啟進程才能看到效果。事實上開發Stone時針對這方面做了不少工作。好處是:程序的性能得到極大的提高。 當然, 客觀上的一些利好因素是: PHP的內存回收已經相當穩定和高效, Swoole穩定性已經在相當多的項目中得到驗證,Laravel代碼質量相當高。

按照Laravel官方文檔安裝laravel,如果已經安裝可以跳過

composer安裝stone內核

composer require stone/kernel:dev-master
編輯config / app.php,添加Provider

 'providers' => [

    /*
     * Laravel Framework Service Providers...
     */
    Illuminate\Auth\AuthServiceProvider::class,
    // 省略很多行

    /*
     * Package Service Providers...
     */
    Stone\StoneServiceProvider::class,

    /*
     * Application Service Providers...
     */
    App\Providers\AppServiceProvider::class,
],
編輯app / Console / Kernel.php,添加新命令

protected $commands = [
    \Stone\Console\Commands\StoneServer::class,
];
Stone的安裝已經完成,正常情況下stone:server的命令應該可以正常執行了

php ./artisan stone:server --help

Usage:
    stone:server [options]

Options:
      --debug
      --start
      --reload
      --stop
  -h, --help            Display this help message
  -q, --quiet           Do not output any message
  -V, --version         Display this application version
      --ansi            Force ANSI output
      --no-ansi         Disable ANSI output
  -n, --no-interaction  Do not ask any interactive question
      --env[=ENV]       The environment the command should run under
  -v|vv|vvv, --verbose  Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug

Help:
  A FastCGI server bases on swoole and laravel
下面我們繼續,讓服務器運行起來,首先需要設置一些服務器的參數,我們需要新建一個config / stone.php

<?php
return [
    'server' => [
        'user' => 'www-data', //運行用戶,一般和php-fpm運行用戶相同
        'group' => 'www-data', //運行組,同上
        'domain' => '/var/run/stone-server-fpm.sock', // Unix域套接字地址,使用與nginx進程通信,推薦保持可用,如果系統不支持也可以是ip地址
        'port' => 9101, // 端口
        'handler' => 'App\Servers\Handler', //請求處理器,一個類名
        'pid' => '/var/run/stone.pid', //進程文件
    ]
];
建立Handler,新建app / Servers / Handler.php

<?php namespace App\Servers;

use Stone\Contracts\RequestHandler;
use Response;

class Handler implements RequestHandler
{
    public function process()
    {
        return Response::make('hello, stone server!');
    }

    public function onWorkerStart()
    {   
    }

    public function handleException($e)
    {   
    }
}
啟動服務器,正常情況下會顯示一個ok

php artisan swoole:http stop
php artisan swoole:http start

sudo php artisan stone:server --stop
sudo php artisan stone:server --start

2020年6月9日 星期二

《面試官別再問》JavaScript 動態變數怎麼寫,動態呼叫function函式

//在全域宣告一個變數,他會跑進window的物件中,我們把該變數當作特性去讀寫他
//過程:
var i = "0";
this['str'+i] = 100;
//結果:
console.log(str0); //會回傳100

//function內也是一樣
function func(){
var a = '123';
for(i=0;i&lt;=5;i++){
this['a'+i] = i;
console.log(this['a'+i]);
}
}
func();
//會印出6次結果,分別是0~5

PHP變數和函數的特異功能

  • for-loop 中最常使用到動態變數
<?php
// price name list
$priceNameList = array('Original', 'VIP', 'Employee');

// price list
$priceList = array(300, 200, 100);
$total = count($priceList);
// dump priceList to meaningful variable name;
for ($i=0; $i < $total; $i++) {
    ${'price'.$priceNameList[$i]} = $priceList[$i];
}

echo 'oringial price: ' . $priceOriginal . "\n";

這樣就可以將變數的名稱做有意義的命名,當然也可以透過 array key value的方式做到。
$priceDictionary = array("Original" => 300,
                         "VIP" => 200,
                         "Employee" => 100);
foreach ($priceDictionary as $key => $value) {
    ${'price'.$key} = $value;
}
echo 'demo 2: oringial price: ' . $priceOriginal . "\n";
更進階的方法,PHP中提供了一個很特別的函式extract(),只要一行就可以做到我們的需求:
extract($priceDictionary, EXTR_PREFIX_ALL, "price");
echo 'demo 3: oringial price: ' . $price_Original . "\n";
這裡需要特別注意的地方是,extract()參數,預設值是 EXTR_OVERWRITE,會把既有變數的值覆蓋。另外 EXTR_PREFIX_ALL 變數會有 _ i.e $price_Original 而不是 $priceOriginal
有關extract()參數請參考 extract manual

2020年5月11日 星期一

vue面試題vue-cli相關知識點

沒有框架的日子
先回想一下在沒有框架的時候,開發者的日常會長什麼樣子吧。

那時最流行的「套件」非 jQuery 莫屬了,語法簡潔、直覺好用的元素選取器,語法便捷的事件監聽註冊,豐富的開發者生態系產出大量的開源套件,以及最重要的,弭平瀏覽器 XHR 差異的 ajax 函式,將複雜的瀏覽器差異藏在套件中,讓開發者只需要專注在想實作的邏輯即可。

透過好用的元素選取器及事件監聽,開發者們可以依據使用者的行為,靈活操作 DOM 元素的結構及樣式,jQuery 的這些特色直到 2019 的現在,都仍是很實用的功能,甚至 程式碼本身 也有許多值得開發者學習的地方;但隨著專案規模逐漸增大,程式複雜度不斷上升,直接操作 DOM 的缺點也就逐漸浮出檯面:

難以維護
HTML、CSS、JavaScript 無法維持原先的各司其職,因為需要透過 JavaScript 處理互動內容,勢必要將結構、樣式寫到 JavaScript 的部份中,也就因此造成架構耦合度提高,程式碼管理困難。

效能低落
在 Reflow 及 Repaint 是什麼? 中有提到 Render Tree 的概念,當 DOM 被改變,勢必要觸發整個 Reflow & Repaint 的流程,頻繁的改動觸發重複渲染,便會讓頁面效能被消耗殆盡。

框架的功能

既然有前述的問題,自然會有強者試圖解決它。歷史進程中有許多大神拋出了方法論,或是實作出解決方案,但這中間的歷史礙於篇幅,就容筆者簡略帶過吧。總之,現今的「框架」其實就是一種提升開發效率、降低維護難度的開發架構。主流的框架如 React、Vue 等,大都擁有這些特性:

問題一:構建的vue-cli 工程都到了哪些技術,它們的作用分別是什麼?

1、vue.js:vue-cli工程的核心,主要特點是 雙向數據綁定 和 組件系統。
2、vue-router:vue官方推薦使用的路由框架。
3、vuex:專為 Vue.js 應用項目開發的狀態管理器,主要用於維護vue組件間共用的一些 變量 和 方法。
4、axios( 或者 fetch 、ajax ):用於發起 GET 、或 POST 等 http請求,基於 Promise 設計。
5、webpack:模塊加載和vue-cli工程打包器。


問題二:vue-cli 工程常用的npm 命令有哪些?

下載 node_modules 資源包的命令:
npm install

啟動 vue-cli 開發環境的 npm命令:
npm run dev

vue-cli 生成 生產環境部署資源 的 npm命令:
npm run build

用於查看 vue-cli 生產環境部署資源文件大小的 npm命令:
npm run build --report

問題三:請說出vue-cli工程中每個文件夾和文件的用處

build 文件夾:用於存放 webpack 相關配置和腳本。開發中僅 偶爾使用 到此文件夾下 webpack.base.conf.js 用於配置 less、sass等css預編譯庫,或者配置一下 UI 庫。
config 文件夾:主要存放配置文件,用於區分開發環境、線上環境的不同。
常用到此文件夾下 config.js 配置開發環境的 端口號、是否開啟熱加載 或者 設置生產環境的靜態資源相對路徑、是否開啟gzip壓縮、npm run build 命令打包生成靜態資源的名稱和路徑等。
dist 文件夾:默認 npm run build 命令打包生成的靜態資源文件,用於生產部署。
node_modules:存放npm命令下載的開發環境和生產環境的依賴包。
src: 存放項目源碼及需要引用的資源文件。
src下assets:存放項目中需要用到的資源文件,css、js、images等。
src下componets:存放vue開發中一些公共組件:header.vue、footer.vue等。
src下emit:自己配置的vue集中式事件管理機制。
src下router:vue-router vue路由的配置文件。
src下service:自己配置的vue請求後台接口方法。
src下page:存在vue頁面組件的文件夾。
src下util:存放vue開發過程中一些公共的.js方法。
src下vuex:存放 vuex 為vue專門開發的狀態管理器。
src下app.vue:使用標籤<route-view></router-view>渲染整個工程的.vue組件。
src下main.js:vue-cli工程的入口文件。
index.html:設置項目的一些meta頭信息和提供<div id="app"></div>用於掛載 vue 節點。
package.json:用於 node_modules資源部 和 啟動、打包項目的 npm 命令管理。

問題四. 什麼是 MVVM?

MVVM 是 Model-View-ViewModel 的縮寫,MVVM 是一種設計思想。 Model 層代表數據模式,也可以在 Model 中定義數據修改和操作的業務邏輯;View 代表 UI 組件,它負責將數據模型轉化爲 UI 展現出來,ViewModel 是一個同步 View 和 Model 的對象。

問題五. 父組件向子組件傳值的方法?

父組件傳遞的數據子組件用 props 方法接收。

子組件通過兩種方式接收:可以傳遞任何類型(數組,對象,各種數據類型等等)

*props:[‘title’,‘likes’,‘isPublished’,‘author’];

*props:{title:String,likes:Number}

詳細介紹看這篇:Vue 父組件向子組件傳值

https://blog.csdn.net/qq_34928693/article/details/80539350

問題六. 子組件向父組件傳值的方法?

子組件向父組件傳值用this.$emit(key,value) ,父組件接收的時候需要在父組件中創建的子組件的標籤中綁定Key,格式:@Key=“方法名”,父組件聲明這個方法,方法帶參數,這個參數就是子組件傳遞的Value。

詳細介紹看這篇:Vue 子組件向父組件傳值

https://blog.csdn.net/sisi_chen/article/details/81635216

問題七. Vuex 是什麼?哪種功能場景使用它?

Vuex 是專門爲 Vue.js 設計的狀態管理模式,它採用集中式儲存管理 Vue 應用中所有組件的狀態,並以相應的規則保證狀態以一種可預測的方式發生變化。

當項目龐大的時候使用它:

*需要動態的註冊響應式數據;

*需要命名空間 namespace 來管理組織我們的數據;

*希望通過插件,來更改記錄;方便測試;以上這些需要和希望,都是我們 vuex 需要做的一些事情。

問題八. Vuex 有哪幾種屬性?

*state:基本數據

*getters:從基本數據派生的數據

*mutations:提交更改數據的方法,同步!

*actions:像一個裝飾器,包裹 mutations,使之可以異步。

*modules:模塊化 Vuex。

6. 如何讓 CSS 旨在當前組件中起作用?

當前組件的 < style> 標籤修改爲 < style scoped>

問題九.生命週期是什麼
Vue 實例有一個完整的生命週期,也就是從開始創建、初始化數據、編譯模版、掛載Dom -> 渲染、更新-> 渲染、卸載等一系列過程,我們稱這是Vue的生命週期。

各個生命週期的作用

生命週期描述
beforeCreate組件實例被創建之初,組件的屬性生效之前
created組件實例已經完全創建,屬性也綁定,但真實dom還沒有生成,$el還不可用
beforeMount在掛載開始之前被調用:相關的render 函數首次被調用
mountedel 被新創建的vm.$el 替換,並掛載到實例上去之後調用該鉤子
beforeUpdate組件數據更新之前調用,發生在虛擬DOM 打補丁之前
update組件數據更新之後
activitedkeep-alive專屬,組件被激活時調用
deadctivatedkeep-alive專屬,組件被銷毀時調用
beforeDestory組件銷毀前調用
destoryed組件銷毀後調用

2020年1月21日 星期二

[PHP 安全] OWASP 維護的PHP 安全配置速查表

介紹

這個頁面的目的是為了幫助那些配置PHP 和運行它的web 服務器的人確保它的安全性。
下面你將找到有關php.ini文件的正確配置信息。

php.ini

下面的一些設置需要適應你的系統,特別是session.save_pathsession.cookie_path(例如:/var/www/mysite),和session.cookie_domain(例如:ExampleSite.com)。
你還應該運行PHP 7.2或者更高版本。如果你運行的版本是PHP 7.0和PHP 7.1 ,你將在下面的幾個地方使用略有不同的值(看內聯的註釋)。最後,查看PHP文檔 以獲得關於php.ini配置文件中每個值的參考。
你可以在一個現成的php.ini文件中找到以下配置的副本此處

PHP 錯誤處理

expose_php              = Off
error_reporting         = E_ALL
display_errors          = Off
display_startup_errors  = Off
log_errors              = On
error_log               = /valid_path/PHP-logs/php_error.log
ignore_repeated_errors  = Off
請注意:你需要在生產環境中display_errors 設置成  Off,同時最好養成經常查看這些日誌的好習慣。

PHP 通用設置

doc_root                = /path/DocumentRoot/PHP-scripts/
open_basedir            = /path/DocumentRoot/PHP-scripts/
include_path            = /path/PHP-pear/
extension_dir           = /path/PHP-extensions/
mime_magic.magicfile    = /path/PHP-magic.mime
allow_url_fopen         = Off
allow_url_include       = Off
variables_order         = "GPCS"
allow_webdav_methods    = Off
session.gc_maxlifetime  = 600
allow_url_* 很容易發生  LFI還有  RFI完全漏洞。

PHP上傳文件處理

file_uploads            = On
upload_tmp_dir          = /path/PHP-uploads/
upload_max_filesize     = 2M
max_file_uploads        = 2
如果你的應用沒有使用文件上傳功能,或者說用戶唯一的輸入上傳的方式是通過沒有包含文檔附件的表單提交,  file_uploads 應當被設置成  Off

PHP 可執行處理

enable_dl               = Off
disable_functions       = systemexec, shell_exec, passthru, phpinfo, show_source, highlight_file, popen, proc_open, fopen_with_path, dbmopen, dbase_open, putenv, move_uploaded_file, chdirmkdirrmdirchmodrename, filepro, filepro_rowcount, filepro_retrieve, posix_mkfifo
# 请查看:http://ir.php.net/features.safe-mode
disable_classes         = 
以上是PHP中存在危險的方法和類.。你應當禁用其中不會使用到的方法和類。

PHP session 處理

Session 設置中有一些需要重點關注的值, 將session.name 改成新的是個很好的練習.
 session.save_path                = /path/PHP-session/
 session.name                     = myPHPSESSID
 session.auto_start               = Off
 session.use_trans_sid            = 0
 session.cookie_domain            = full.qualified.domain.name
 #session.cookie_path             = /application/path/
 session.use_strict_mode          = 1
 session.use_cookies              = 1
 session.use_only_cookies         = 1
 session.cookie_lifetime          = 14400 # 4小时 
 session.cookie_secure            = 1
 session.cookie_httponly          = 1
 session.cookie_samesite          = Strict
 session.cache_expire             = 30 
 session.sid_length               = 256
 session.sid_bits_per_character   = 6 # PHP 7.2+
 session.hash_function            = 1 # PHP 7.0-7.1
 session.hash_bits_per_character  = 6 # PHP 7.0-7.1

更多的安全隱患的檢查

session.referer_check   = /application/path
memory_limit            = 50M
post_max_size           = 20M
max_execution_time      = 60
report_memleaks         = On
track_errors            = Off
html_errors             = Off
文章轉自:https://learnku.com/php/t/26973