轉載的一些面試題

一. 輸入url後的加載過程

從輸入 URL 到頁面加載完成的過程當中都發生了什麼javascript

計算機網絡體系結構css

  • 應用層(HTTP、SMTP、FTP、POP3)
  • 運輸層(TCP、UDP)
  • 網絡層(IP(路由器))
  • 數據鏈路層(網橋(CSMA/CD、PPP))
  • 物理層(集線器)

1. 查找域名對應IP地址

這一步包括 DNS 具體的查找過程,包括:瀏覽器緩存->系統緩存->路由器緩存...
(1) 瀏覽器搜索本身的 DNS 緩存(維護一張域名與 IP 地址的對應表);
(2) 搜索操做系統中的 DNS 緩存(維護一張域名與 IP 地址的對應表);
(3) 搜索操做系統的 hosts 文件( Windows 環境下,維護一張域名與 IP 地址的對應表);
(4) 操做系統將域名發送至 LDNS(本地區域名服務器),LDNS 查詢 本身的 DNS 緩存(通常查找成功率在 80% 左右),查找成功則返回結果,失敗則發起一個迭代 DNS 解析請求:html

① LDNS 向 Root Name Server (根域名服務器,如 com、net、org等的解析的頂級域名服務器的地址)發起請求,此處,Root Name Server 返回 com 域的頂級域名服務器的地址;前端

② LDNS 向 com 域的頂級域名服務器發起請求,返回 baidu.com 域名服務器地址;vue

③ LDNS 向 baidu.com 域名服務器發起請求,獲得 www.baidu.com 的 IP 地址;java

(5) LDNS 將獲得的 IP 地址返回給操做系統,同時本身也將 IP 地址緩存起來;node

(6) 操做系統將 IP 地址返回給瀏覽器,同時本身也將 IP 地址緩存起來;react

2. 創建鏈接(TCP的三次握手)

(1) 主機向服務器發送一個創建鏈接的請求;git

(2) 服務器接到請求後發送贊成鏈接的信號;es6

(3) 主機接到贊成鏈接的信號後,再次向服務器發送了確認信號 ;

注意:這裏的三次握手中主機兩次向服務器發送確認,第二次是爲了防止已失效的鏈接請求報文段傳至服務器致使錯誤。

3. 構建網頁

(1) 瀏覽器根據 URL 內容生成 HTTP 請求,請求中包含請求文件的位置、請求文件的方式等等;

(2) 服務器接到請求後,會根據 HTTP 請求中的內容來決定如何獲取相應的 HTML 文件;

(3) 服務器將獲得的 HTML 文件發送給瀏覽器;

(4) 在瀏覽器尚未徹底接收 HTML 文件時便開始渲染、顯示網頁;

(5) 在執行 HTML 中代碼時,根據須要,瀏覽器會繼續請求圖片、音頻、視頻、CSS、JS等文件,過程同請求 HTML ;

瀏覽器渲染展現網頁過程

  1. HTML代碼轉化爲DOM(DOM Tree)
  2. CSS代碼轉化成CSSOM(CSS Object Model)
  3. 結合DOM和CSSOM,生成一棵渲染樹(包含每一個節點的視覺信息)(Render Tree)
  4. 生成佈局(layout),即將全部渲染樹的全部節點進行平面合成
  5. 將佈局繪製(paint)在屏幕上

4. 斷開鏈接(TCP的四次揮手)

(1) 主機向服務器發送一個斷開鏈接的請求;

(2) 服務器接到請求後發送確認收到請求的信號;(此時服務器可能還有數據要發送至主機)

(3) 服務器向主機發送斷開通知;(此時服務器確認沒有要向主機發送的數據)

(4) 主機接到斷開通知後斷開鏈接並反饋一個確認信號,服務器收到確認信號後斷開鏈接;

注意:這裏的四次揮手中服務器兩次向主機發送消息,第一次是回覆主機已收到斷開的請求,第二次是向主機確認是否斷開,確保數據傳輸完畢。


三次握手 && 四次揮手

二. 有了解過Common.js嗎?

發現這方面的資料不多啊,都沒有相中的比較好理解的。

淺析JS中的模塊規範(CommonJS,AMD,CMD)

前端模塊化(CommonJs,AMD和CMD)


前端模塊化

前端模塊化

三. 有了解過React.js嗎?

React.js 只是一個視圖庫

  (1)聲明式設計

  (2)高效:經過對DOM的模擬,最大限度的減小與DOM的交互。

  (3)靈活:能夠與已知的框架或庫很好的配合。

  (4)JSX:是js語法的擴展,不必定使用,但建議用。

  (5)組件:構建組件,使代碼更容易獲得複用,可以很好地應用在大項目的開發中。

  (6)單向響應的數據流:React實現了單向響應的數據流,從而減小了重複代碼,這也是解釋了它爲何比傳統數據綁定更簡單。

react 經過prop管理組件通訊,經過state 驅動視圖比較差別進行更新操做

做者:第七頁
連接:https://www.zhihu.com/question/39825457/answer/83544390
來源:知乎
著做權歸做者全部,轉載請聯繫做者得到受權。

angular 是MV* 框架, react是用來構建可重複使用的UI組件的, 能夠當作是個提供工具的library。
react 能夠和 angular 的 directive作比較。 這樣比較的話, react是比angular directive 在組建UI上更powerful的。

做者:空空
連接:https://www.zhihu.com/question/23444167/answer/24957302
來源:知乎
著做權歸做者全部,轉載請聯繫做者得到受權。

React.js 初學者應該知道的 9 件事

React之特色及常見用法

React 入門實例教程

請問 React 和 Angular 各有什麼優缺點,各自又適合什麼開發場景?


四. angular和vue的區別

唉,這個真的太難總結了,求評論!!!

Vue擁有相似 Angular 的雙向數據綁定,以及相似 React 的虛擬DOM。


angular && vue && react

Vue.js 很好,但會比 Angular 或 React 更好嗎?

vue.js與angular,react等框架分析比較

淺析angular,react,vue.js jQuery使用區別


五. less的特色

每次被問到這個我只能想起less中的定義變量,用過久less都忘了css不能嵌套,醉了醉了。

  1. 變量
  2. 混合(Mixins)
  3. 嵌套規則
  4. 運算
  5. 函數
  6. 命名空間
  7. 做用域
  8. 註釋
  9. 導入(Import)

Less語言特性

sass-vs-less

Sass和Less的區別

sass 與 less 的區別與學習


六. less的原理

本質上,less 包含一套自定義的語法及一個解析器,用戶根據這些語法定義本身的樣式規則,這些規則最終會經過解析器,less 把這些樣式規則編譯成瀏覽器能夠識別的 css 樣式。less 並無裁剪 css 原有的特性,更不是用來取代 css 的,而是在現有 css 語法的基礎上,爲 css 加入程序式語言的特性。less 最終須要編譯成 css 文件才能起到樣式的效果,咱們能夠稱 less 爲 css 樣式生成工具。


七. gulp的特色

  1. 使用 gulp.js,你的構建腳本是代碼,而不是配置文件;
  2. 使用標準庫(node.js standard library)來編寫腳本;
  3. 插件都很簡單,只負責完成一件事-基本上都是 20 行左右的函數;
  4. 任務都以最大的併發數來執行;
  5. Gulp是一個基於流的構建系統,使用代碼優於配置的策略。輸入/輸出(I/O)是基於「流式」的。

做用

  1. Sass、Less編譯
  2. Css Js 圖片壓縮
  3. Css Js 合併
  4. Css Js 內聯
  5. Html的include功能
  6. Autoprefixer(自動處理瀏覽器css前綴)
  7. 自動刷新
  8. 去緩存
  9. Handlebars模板文件的預編譯
  10. 雪碧圖
  11. ESLint
  12. rem移動端適配方案

其餘補充

  gulp grunt
速度
格式 和node差很少 json套json
操做基於 二進制流 文件

gulp VS grunt

前端工程的構建工具對比 Gulp vs Grunt


模塊化 && 構建

dist是指distribution——分配,分發——發佈完成的文件夾通常命名dist。

dest則是destination——目的地,終點——用於grunt文件路徑相關的配置項,通常會和src配對出現。好比文件壓縮插件:壓縮源(src)文件,生成壓縮包到(dest)。

做者:峯子
連接:https://www.zhihu.com/question/29199796/answer/82862432
來源:知乎
著做權歸做者全部,轉載請聯繫做者得到受權。

常規GruntFile.js && gulpFile.js

  • GruntFile.js
<script> module.exports = function(grunt) { // 導入模塊 grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.loadNpmTasks('grunt-contrib-htmlmin'); grunt.loadNpmTasks('grunt-contrib-imagemin'); grunt.loadNpmTasks('grunt-contrib-watch'); // 配置任務 grunt.initConfig({ // js壓縮 默認加密壓縮 uglify: { // 主任務名稱 options: { // [配置選項] mangle: false // 是否加密壓縮 }, a: { // 子任務名稱 expand: true, // 是否分開壓縮 src: 'js/*.js', // 源文件 dest: 'build' // 目標文件 自動建立源文件文件夾 } }, cssmin: { a: { expand: true, src: 'css/*.css', dest: 'build' } }, htmlmin: { options: { removeComments: true, // 是否移除註釋 collapseWhitespace: false // 是否去掉空白 }, a: { src: '*.html', dest: 'build' } }, // imagemin: { // a: { // expand: true, //分開執行 // cwd: 'images', // src: ['**/*.{png,jpg}'], // dest: 'build/images' // } // }, watch: { a: { files: ['*.html', 'css/*.css', 'js/*.js'], tasks: ['cssmin', 'htmlmin', 'uglify'] } } }); // 註冊一個默認任務 grunt.registerTask('default', ['uglify', 'cssmin', 'htmlmin', 'watch']); } </script>
  • gulpfile.js
<script> // 導入模塊 var gulp = require('gulp'); var cssmin = require('gulp-cssmin'); var uglify = require('gulp-uglify'); var htmlmin = require('gulp-htmlmin'); var concat = require('gulp-concat'); var rename = require('gulp-rename'); // 更名 // 配置任務 gulp.task('uglify:css', function() { gulp.src('css/*.css') .pipe(cssmin()) // 壓縮 .pipe(concat('all.min.css')) // 合併 .pipe(gulp.dest('build/css')) // 輸出 }); gulp.task('uglify:js', function() { gulp.src('js/*.js') .pipe(uglify()) // 壓縮 .pipe(gulp.dest('build/js')) // 輸出 }); gulp.task('uglify:html', function() { gulp.src('*.html') .pipe(htmlmin({ // 壓縮 collapseWhitespace: true, removeComments: true })) .pipe(gulp.dest('build')) // 輸出 }); gulp.watch('*.*', ['uglify:css', 'uglify:js', 'uglify:html']); gulp.task('default', ['uglify:css', 'uglify:js', 'uglify:html']); </script>
<script> var gulp = require('gulp'); var uglify = require('gulp-uglify'); var clean = require('gulp-clean-css'); var sass = require('gulp-sass'); gulp.task('uglify',function(){ return( gulp.src('./src/*.js') .pipe(uglify()) .pipe(gulp.dest('dist')) ) }) gulp.task('minify-css',function(){ return ( gulp.src('./src/*.css') .pipe(clean()) .pipe(gulp.dest('dist')) ) }) gulp.task('compile-sass',function(){ return ( gulp.src('./src/*.scss') .pipe(sass().on('error', sass.logError)) .pipe(gulp.dest('dist')) ) }) gulp.task('default',function(){ gulp.watch('./src/*.js',['uglify']); gulp.watch('./src/*.css',['minify-css']); gulp.watch('./src/*.scss',['compile-sass']); }) </script>

八. ajax的原理

  • 在舊的交互方式中,由用戶觸發一個HTTP請求到服務器,服務器對其進行處理後再返回一個新的HTHL頁到客戶端, 每當服務器處理客戶端提交的請求時,客戶都只能空閒等待,而且哪怕只是一次很小的交互、只需從服務器端獲得很簡單的一個數據,都要返回一個完整的HTML頁,而用戶每次都要浪費時間和帶寬去從新讀取整個頁面。而使用Ajax後用戶從感受上幾乎全部的操做都會很快響應沒有頁面重載(白屏)的等待。

  • Ajax的原理簡單來講是在用戶和服務器之間加了—箇中間層(AJAX引擎),經過XmlHttpRequest對象來向服務器發異步請求,從服務器得到數據,而後用javascript來操做DOM而更新頁面。使用戶操做與服務器響應異步化。這其中最關鍵的一步就是從服務器得到請求數據。

    • Ajax的過程只涉及JavaScript、XMLHttpRequest和DOM。XMLHttpRequest是ajax的核心機制,它是在IE5中首先引入的,是一種支持異步請求的技術。簡單的說,也就是javascript能夠及時向服務器提出請求和處理響應,而不阻塞用戶。達到無刷新的效果。

天天10個前端知識點:ajax && jsonp

ajax過程

  1. 得到ajax
  2. 打開地址
  3. 發送數據
  4. 接收數據
<script>
 // 1.得到ajax if (window.XMLHttpRequest) { //查看當前瀏覽器XMLHttpRequest是不是全局變量 var oAjax = new XMLHttpResquest(); } else { var oAjax = new ActiveXObject('Microsoft.XMLHTTP'); //IE6,傳入微軟參數 } // 2.打開地址 switch (json.type.toLowerCase()) { case 'get': oAjax.open('GET', json.url + '?' + jsonToURL(json.data), true); // 提交方式(大寫),url,是否異步 oAjax.send(); // 3.發送數據 break; case 'post': oAjax.open('POST', json.url, true); oAjax.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); oAjax.send(jsonToURL(json.data)); // 3.發送數據 break; } // 4.接收數據 oAjax.onreadystatechange = function() { //監控狀態 if (oAjax.readyState == 4) { json.complete && json.complete(); if (oAjax.status >= 200 && oAjax.status < 300 || oAjax.status == 304) { json.success && json.success(oAjax.responseText); //執行成功的回調函數, responseText爲響應內容 } else { json.error && json.error(oAjax.status); //執行失敗的回調函數 } } }; </script>

九. 有了解過ES6嗎?

哈哈,這個後面會寫一整篇,敬請期待!

【探祕ES6】系列專欄(一):ES6簡介


十. git merge

git merge 和 git rebase 小結


十一. less不依靠構建轉css

我猜這道面試題應該也不讓用 lessc ,哈哈哈!

依舊求評論,我只會lessc和構建轉化誒。

甩上gulp構建轉化

<script> var gulp = require('gulp'), less = require('gulp-less'); gulp.task('testLess', function() { gulp.src(['src/less/index.less', 'src/less/detail.less']) //多個文件以數組形式傳入 .pipe(less()) .pipe(gulp.dest('src/css')); //將會在src/css下生成index.css以及detail.css }); gulp.task('testWatch', function() { gulp.watch('src/**/*.less', ['testLess']); //當全部less文件發生改變時,調用testLess任務 }); </script>

十二. 冒泡、快排

這個後面也有一篇簡單的算法篇,敬請期待!

  • 冒泡排序
    每次比較相鄰的兩個數,若是後一個比前一個小,換位置。
    時間複雜度:O(n^2)
<script>
    var arr = [3, 1, 4, 6, 5, 7, 2]; function bubbleSort(arr) { for (var i = 0; i < arr.length - 1; i++) { for(var j = 0; j < arr.length - 1; j++) { if(arr[j + 1] < arr[j]) { var temp; temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } } console.log(bubbleSort(arr)); </script>
  • 快速排序
    採用二分法,取出中間數,數組每次和中間數比較,小的放到左邊,大的放到右邊。
    時間複雜度:O(nlog2(n))
<script>
    var arr = [3, 1, 4, 6, 5, 7, 2]; function quickSort(arr) { if(arr.length == 0) { return []; // 返回空數組 } var cIndex = Math.floor(arr.length / 2); var c = arr.splice(cIndex, 1); var l = []; var r = []; for (var i = 0; i < arr.length; i++) { if(arr[i] < c) { l.push(arr[i]); } else { r.push(arr[i]); } } return quickSort(l).concat(c, quickSort(r)); } console.log(quickSort(arr)); </script>

十三. promise

Promise對象有如下兩個特色。

  1. 對象的狀態不受外界影響。Promise對象表明一個異步操做,有三種狀態:Pending(進行中)、Resolved(已完成,又稱 Fulfilled)和Rejected(已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。這也是Promise這個名字的由來,它的英語意思就是「承諾」,表示其餘手段沒法改變。

  2. 一旦狀態改變,就不會再變,任什麼時候候均可以獲得這個結果。Promise對象的狀態改變,只有兩種可能:從Pending變爲Resolved和從Pending變爲Rejected。只要這兩種狀況發生,狀態就凝固了,不會再變了,會一直保持這個結果。就算改變已經發生了,你再對Promise對象添加回調函數,也會當即獲得這個結果。這與事件(Event)徹底不一樣,事件的特色是,若是你錯過了它,再去監聽,是得不到結果的。

ECMAScript 6入門 - Promise對象


十四. 性能優化

詳見性能優化篇!


十五. js的冒泡(Bubbling Event)和捕獲(Capture Event)的區別

js之事件冒泡和事件捕獲詳細介紹

  1. 冒泡型事件:事件按照從最特定的事件目標到最不特定的事件目標(document對象)的順序觸發。

  2. 捕獲型事件(event capturing):事件從最不精確的對象(document 對象)開始觸發,而後到最精確(也能夠在窗口級別捕獲事件,不過必須由開發人員特別指定)。

  3. DOM事件流:同時支持兩種事件模型:捕獲型事件和冒泡型事件,可是,捕獲型事件先發生。兩種事件流會觸及DOM中的全部對象,從document對象開始,也在document對象結束。
    DOM事件模型最獨特的性質是,文本節點也觸發事件(在IE中不會)。

示例
假設一個元素div,它有一個下級元素p。

<div>   <p>元素</p> </div>

這兩個元素都綁定了click事件,若是用戶點擊了p:

  • 事件捕獲
    當你使用事件捕獲時,父級元素先觸發,子級元素後觸發,即div先觸發,p後觸發。
  • 事件冒泡
    當你使用事件冒泡時,子級元素先觸發,父級元素後觸發,即p先觸發,div後觸發。

addEventListener函數,它有三個參數,第三個參數如果true,則表示採用事件捕獲,如果false,則表示採用事件冒泡。
IE只支持事件冒泡,不支持事件捕獲。


Paste_Image.png

阻止冒泡

• 在W3c中,使用stopPropagation()方法
• 在IE下設置cancelBubble = true

在捕獲的過程當中stopPropagation();後,後面的冒泡過程也不會發生了。

阻止捕獲

阻止事件的默認行爲,例如click <a>後的跳轉
• 在W3c中,使用preventDefault()方法;
• 在IE下設置window.event.returnValue = false;


十六. 數組的翻轉(非reverse)

<script>
    var arr=[1,2,3,4]; var arr2=[]; while(arr.length) { var num=arr.pop(); arr2.push(num); } alert(arr2); </script>

數組更多應用詳見:天天10個前端知識點:數組應用篇


十七. js的Object和其餘語言的object的區別

js對象的建立 js對象和java對象的不一樣

面向對象分爲基於原型的面向對象和基於模板的面向對象。

  • Java:基於模板的面向對象。
class A { private String name; public void fun(){ } } A a = new A(); a.fun();
  • JavaScript:基於原型的面向對象,基於事件的網頁腳本語言。
<script> function CreateObject() { } CreateObject.prototype = { constructor: CreateObject, // 可特地聲明constructor指向 CreateObject name: 'xxx', age: '11', children: ['aaa', 'bbb'], getName: function() { return this.name; } } var p = new CreateObject(); console.log(p.name); // 'xxx' </script>

十八. js的Element和Node的區別

JavaScript中Element與Node的區別,children與childNodes的區別

  • Element繼承了Node類,也就是說Element是Node多種類型中的一種。
  • children是Element的屬性,childNodes是Node的屬性

HTML中的Node和Element的區別

  • NODE是相對TREE這種數據結構而言的。TREE就是由NODE組成。
    node有幾個子類型:Element,Text,,Attribute,RootElement,Comment,Namespace等。
  • ELEMENT則是HTML裏的概念,是元素即標籤包含內部屬性及內容的整體,是HTML中的數據的組成部分之一。

十九. svn與git的區別

  1. git是分佈式的,svn不是。
    git跟svn同樣有本身的集中式版本庫或服務器。但git更傾向於被使用於分佈式模式,克隆版本庫後即便沒有網絡也可以commit文件,查看歷史版本記錄,建立項目分支等,等網絡再次鏈接上Push到服務器端。

  2. git把內容按元數據方式存儲,而svn是按文件。
    全部的資源控制系統都是把文件的元信息隱藏在一個相似.svn,.cvs等的文件夾裏。
    git目錄是處於你的機器上的一個克隆版的版本庫,它擁有中心版本庫上全部的東西,例如標籤,分支,版本記錄等。

  3. git沒有一個全局的版本號,svn有。

  4. git的內容完整性優於svn。
    由於git的內容存儲使用的是SHA-1哈希算法。

  5. git能夠有無限個版本庫,svn只能有一個指定中央版本庫。
    當svn中央版本庫有問題時,全部工做成員都一塊兒癱瘓直到版本庫維修完畢或者新的版本庫設立完成。
    每個git都是一個版本庫,區別是它們是否擁有活躍目錄(Git Working Tree)。若是主要版本庫(例如:置於GitHub的版本庫)有問題,工做成員仍然能夠在本身的本地版本庫(local repository)提交,等待主要版本庫恢復便可。工做成員也能夠提交到其餘的版本庫!


二十. 定時器

這是一道筆試題,小白就是小白啊,還第一次見到定時器的第三個參數,仍是這麼寫的。

廣義上咱們遇到定時器的題目通常是這樣的

  • setTimeout
<script> for (var i = 0; i < 3; i++) { var t = setTimeout(function() { console.log(i); // 2. 輸出三次3 }, 10); } console.log(i); // 1. 3 </script>

此次碰見的是這樣的:

循環只進行兩次

<script> for (var i = 1; i < 4; i++) { var t = setTimeout(function(i) { console.log(i); // 2. 1 4.2 console.log(t); // 3. 3 5.3 clearTimeout(t); }, 10, i); } console.log(i); // 1. 4 </script>

因而我檢測瞭如下變形

循環只進行兩次

<script> for (var i = 1; i < 4; i++) { var t = setTimeout(function(i) { console.log(i); // 2. 2 4. 2 console.log(t); // 3. 3 5. 3 clearTimeout(t); }, 10, 2); } console.log(i); // 1. 4 </script>

循環只進行兩次

<script> for (var i = 1; i < 4; i++) { var t = setTimeout(function(i) { console.log(i); // 2. 2 4. 2 console.log(t); // 3. 3 5. 3 clearTimeout(t); }, 10, 2); } console.log(i); // 1. 4 </script>

循環只進行兩次

<script> for (var i = 1; i < 4; i++) { var t = setTimeout(function(i, t) { console.log(i); // 2. 2 4. 2 console.log(t); // 3. 3 5. 3 clearTimeout(t); }, 10, 2, 3); } console.log(i); // 1. 5 </script>

只有此次是循環輸出3次

<script> for (var i = 1; i < 4; i++) { var t = setTimeout(function(i, t) { console.log(i); // 2. 1 4. 2 6. 3 console.log(t); // 3. undefined 5. 1 7. 2 clearTimeout(t); }, 10, i, t); } console.log(i); // 1. 5 </script>
  • setInterval
<script> for (var i = 0; i < 4; i++) { var t = setInterval(function() { console.log(i); // 2. 一直輸出4 }, 10); } console.log(i); // 1. 4 </script>

此次碰見的長這樣:

<script> for (var i = 0; i < 4; i++) { var t = setInterval(function(i, t) { console.log(i); // 2. 0,1,2,3,3,3,... clearInterval(t); }, 10, i, t); } console.log(i); // 1. 4 </script>

因而我作了如下測試

<script> for (var i = 1; i < 4; i++) { var t = setInterval(function(i, t) { console.log(i); // 2. 2 4. 2 6. 2... console.log(t); // 3. 3 5. 3 7. 3... clearInterval(t); }, 10, 2, 3); } console.log(i); // 1. 4 </script>
<script> for (var i = 0; i < 4; i++) { var t = setInterval(function(i, t) { console.log(i); // 2. 0 4. 1 6. 2 8. 3 10. 3... console.log(t); // 3. undefined 5. 1 7. 2 9. 3 11. 3... clearInterval(t); }, 10, i, t); } console.log(i); // 1. 4 </script>
相關文章
相關標籤/搜索