面試題總結(jié)liebao

1. 跨域問題

  • jsonp: 利用script標(biāo)簽不受同源策略限制的特點(diǎn), 協(xié)商好一個(gè)callback參數(shù), 當(dāng)然這個(gè)參數(shù)是由請(qǐng)求方定的
  • h5新方法: window.postMessage, 首先要有一個(gè)src是另一個(gè)域頁面的ifrmae標(biāo)簽, 并且監(jiān)聽一個(gè)onload事件, 然后在onload函數(shù)里獲取到這個(gè)ifrmae標(biāo)簽, 并通過.contentWindow獲取到另一個(gè)域的頁面的window對(duì)象, 使用這個(gè)window對(duì)象調(diào)用postMessage('XXX')方法, 傳遞數(shù)據(jù), 最后在另一個(gè)域的頁面里, 調(diào)用window.onmessage事件, 通過 事件對(duì)象e.data獲取傳遞的內(nèi)容
  • 還可以用服務(wù)器代理的方式, 我用過node和axios實(shí)現(xiàn)過
  • window.name: 它有一個(gè)特性就是, 在窗口生命周期沒有結(jié)束之前(未關(guān)閉之前)都只會(huì)共享一個(gè)window.name, 這樣, 當(dāng)我在a.html里設(shè)置了一個(gè)window.name, 頁面跳轉(zhuǎn)b.html后, 這個(gè)window.name不會(huì)改變, 還是a.html里設(shè)置的, 就相當(dāng)于把a(bǔ).html里的數(shù)據(jù)傳到了b.html中. 具體實(shí)現(xiàn):在data.html頁面設(shè)置好window.name利用ifrmae標(biāo)簽載入data.html頁面, 當(dāng)ifrmae載入date.html時(shí)候, 用一個(gè)函數(shù)用來獲取data.html的window.name,

2. 閉包

  • js分全局作用域和函數(shù)作用域, 通過作用域鏈, 函數(shù)作用域可以訪問到包含環(huán)境和全局作用域, 全局作用域無法直接訪問到函數(shù)作用域, 只有通過閉包(函數(shù)中的函數(shù)), 將父級(jí)里的數(shù)據(jù)return出去, 然后在把閉包return出去, 閉包能一直訪問到父級(jí)的數(shù)據(jù), 說明父級(jí)里的數(shù)據(jù)一直存在在內(nèi)存中, 所以閉包可能會(huì)導(dǎo)致內(nèi)存泄露
  • document.domain: 將兩個(gè)頁面的document.domain設(shè)置成一樣的, 就可以通過ifrmae.contentWindow方法, 訪問到通過ifrmae載入的頁面的window對(duì)象了,也能傳值了

3. css3動(dòng)畫

4. 頁面性能問題解決和分析

  • 瀏覽器渲染的過程
    -- html轉(zhuǎn)化為dom
    -- css轉(zhuǎn)化成cssom
    -- 結(jié)合dom和cssom生成渲染樹
    -- 生成布局 flow
    -- 將布局繪制到頁面上 paint
    *注意: 用js獲取offsetXXX, scrollTop等還有g(shù)etComputedStyle()的時(shí)候會(huì)立即出發(fā)回流(reflow), 所以不要吧這些讀操作和寫操作放到一個(gè)語句里
    *原則: 樣式表越簡(jiǎn)單, 回流和重繪越快. dom層級(jí)越高, 成本就越高. table成本高與div
  • 提高性能技巧:
    -- 讀操作寫在一起, 寫操作也在一起, 兩種操作不要混在一起
    -- 樣式是通過回流(重排)得到的, 最好緩存下
    -- 不要一條條改變樣式, 盡量操作class
    -- 如果需要對(duì)摸個(gè)元素進(jìn)行多次操作, 可以先將其設(shè)置成display:none, 在隨便操作n次, 完事后再display: block
    -- 使用虛擬dom腳本, 例如react或vue
    -- window.requestAnimationFrame()調(diào)節(jié)重繪
  • js優(yōu)化:
    -- 減少作用域鏈查找, 在當(dāng)前執(zhí)行環(huán)境緩存一下包含環(huán)境或全局執(zhí)行環(huán)境的數(shù)據(jù);
    -- 字符串拼接盡量避免使用 + , 使用數(shù)組的join();
    -- 優(yōu)化循環(huán), 簡(jiǎn)化循環(huán)體, 簡(jiǎn)化終止條件, 比如 for(var i = 0,len= arr.length; i < len; i ++);
    -- switch語句更快;
    -- 變量聲明提倡 一個(gè)var
    -- 使用事件委托js用addlistenerEvent, jq用 on
  • 減少http請(qǐng)求, 合并css,js, 使用雪碧圖,
  • 圖片懶加載
  • 靜態(tài)資源用cdn
  • 按需加載資源requirejs

5. 用戶交互設(shè)計(jì)理論

6. js事件綁定

7. 遇到比較難的問題, 怎么解決的

8. 移動(dòng)端開發(fā)經(jīng)驗(yàn)

9. canvas

10. js作用域 - 函數(shù)作用域鏈

11.原型繼承:

// Student的構(gòu)造函數(shù)
function Student(props) {
  this.name = props.name || 'nonamed'
}
Student.prototype.sayHello = function() {
  alert('Hello ' + this.name)
}
// 通過Student擴(kuò)展出PrimaryStudent
function PrimaryStudent() {
  Student.call(this, props)
  this.grade = props.grade || 1
}
// 聲明空對(duì)象
function F() {}
// 把空對(duì)象原型指向Student
F.prototype = Student.prototype
// 把PrimaryStudent的prototype指向F的實(shí)例化對(duì)象
PrimaryStudent.prototype = new F()
// 修復(fù)PrimaryStudent上的構(gòu)造函數(shù)(constructor)
PrimaryStudent.prototype.constructor = PrimaryStudent
// 驗(yàn)證
var xiaoming = new PrimaryStudent({name: 'zxk', grade: 10})
xiaoming.name // 'zxk'
xiaoming.grade // 10
// 驗(yàn)證原型:
xiaoming.__proto__=== PrimaryStudent.prototype // true
xiaoming.__proto__ .__proto__=== Student.prototype // true
// 驗(yàn)證繼承:
xiaoming instanceof PrimaryStudent // true
xiaoming instanceof Student // true

12 排序算法

// 冒泡排序
function sort(arr) {
        for(var i = 0; i < arr.length; i ++) {
            for(var j = 0; j < arr.length; j ++) {
                if (arr[j] > arr[j + 1]) {
                    var oldJ = arr[j]
                    arr[j] = arr[j + 1]
                    arr[j + 1] = oldJ
                }
            }
        }
    }
// 

13 將[1, 2, [3, [4, 5, [6]]]] => [1, 2, 3, 4, 5, 6]

function transArr(arr, res) {
  var res = res || []
  for(var i = 0; i < arr.length; i ++) {
    if(arr[i] instanceof Array) {
      transArr(arr[i], res)
    } else {
      res.push(arr[i])
    }
  }
  return res
}

14 事件委托

  • 好處, 減少dom操作, 提高性能, 為動(dòng)態(tài)插入的元素綁定事件
  • 原理事件冒泡, js -> addlistenerEvent, jQ -> on
  • 使用on去綁定事件, 通過e.target獲取實(shí)際點(diǎn)擊的元素進(jìn)行相應(yīng)的操作
  • jQ使用on去綁定事件, 第二個(gè)參數(shù)填選擇器, 會(huì)將父級(jí)事件代理到這個(gè)選擇器上(使用與動(dòng)態(tài)插入的dom)

15 flex的兼容

  • 舊版: display: box; 過渡: display: flex box; 新版: display: flex
  • 安卓: 2.3+ display: -webkit-box; 4.4+ display: flex
  • ios: 6.1+ display: -webkit-box; 7.1+ display: flex
  • pc: ie10支持 flex, -ms形式
  • 兼容寫法, 都是向下兼容的, so舊版寫法要放到下邊, 否則就會(huì)不起作用
.box{

    display: -webkit-flex;  /* 新版本語法: Chrome 21+ */
    display: flex;          /* 新版本語法: Opera 12.1, Firefox 22+ */
    display: -webkit-box;   /* 老版本語法: Safari, iOS, Android browser, older WebKit browsers. */
    display: -moz-box;      /* 老版本語法: Firefox (buggy) */
    display: -ms-flexbox;   /* 混合版本語法: IE 10 */   
 }
.flex1 {            
    -webkit-flex: 1;        /* Chrome */  
    -ms-flex: 1             /* IE 10 */  
    flex: 1;                /* NEW, Spec - Opera 12.1, Firefox 20+ */
    -webkit-box-flex: 1     /* OLD - iOS 6-, Safari 3.1-6 */  
    -moz-box-flex: 1;       /* OLD - Firefox 19- */       
}

16 模塊化requirejs

  • 引入require.js
  • 配置main.js
require.config({
  baseUrl: 'js',
  paths: {
    app: 'app' // 如果是目錄的話, 這里的名字要和目錄一模一樣, 如果是文件可以不同
  }
})
  • 在html里引入requirejs和data-main入口
//index.html
<script src="js/requirejs" data-main="main"></script>
  • define一個(gè)模塊
// a.js
define(function(){
  return {
    name: 'a'
  }
})
// b.js
define(function(){
  return {
    name: 'b'
  }
})
  • 引入模塊
// index.html
<script>
    require(['app/a'], function(a) {
        console.log(a)
    })
    setTimeout(function() {
        require(['app/b'], function(b) {
            console.log(b)
        })
    }, 3000)
</script>
  • 目錄結(jié)構(gòu)


    屏幕快照 2018-05-26 下午12.57.10.png

17 css布局

  • 左邊固定寬度, 右邊自適應(yīng)
    • 左邊: width: 100px; float: left;右邊: width: auto;margin-left: 100px;
    • flex: 左邊固定寬度, 右邊: flex: 1,
  • 三欄布局左右固定寬度, 中間自適應(yīng)
    • 結(jié)構(gòu)是: 左 - 右 - 中, 左: 固定寬度, float: left; 右: 固定寬度float: right; 中: width: auto; margin-left: 左寬, margin-right: 右寬
  • css選擇器:
    • 類選擇器.class
    • id選擇器: #id
    • 標(biāo)簽選擇器: p
    • 后代選擇器: div p
    • 子代選擇器: div>p
    • 之后選擇器: div+p
    • 屬性選擇器:
  • 偽類選擇器:
  • nth-child()
  • first-child
  • :before - after

18 for循環(huán)和定時(shí)器 與 閉包

//瞬間打出0 - 4
    for(var i = 0; i < 5; i++) {
        console.log(i)
    }
    for(var i = 0; i < 5; i++) {
        setTimeout((function(){ // 自調(diào)用函數(shù), 立即執(zhí)行
            console.log(i)
        })(), i * 1000)
    }
    // 順間打出0, 然后每隔一秒打出1-4
    for(var i = 0; i < 5; i++) {
        (function(i){
            setTimeout(function() {
                console.log(i)
            }, i*1000)
        })(i)
    }
    // 順間打出5, 每隔1秒打出一個(gè)5, 共4個(gè)
    for(var i = 0; i < 5; i++) {
        setTimeout(function() {
            console.log(i)
        }, i*1000)
    }
    for(var i = 0; i < 5; i++) {
        (function(){
            setTimeout(function() {
                console.log(i)
            }, i * 1000)
        })(i)
    }
// promise相關(guān)
    setTimeout(function() {
        console.log(1)
    }, 0)
    new Promise(function executor(resolve){
        console.log(2)
        for(var i = 0; i < 1000; i++) {
            i == 999 && resolve(); 
        }
        console.log(3)
    }).then(function() {
        console.log(4)
    })
    console.log(5)
    // logs 2 > 3 > 5 > 4 > 1, promise的then()會(huì)放在當(dāng)前tick的最末尾, 但是setTimeout會(huì)把函數(shù)踢到下一輪tick中

18 js高階面試

  • 描述js中的繼承和原型鏈, 并舉例
    1. js并沒有類的概念, 而是通過原型鏈實(shí)現(xiàn)的繼承, 每個(gè)對(duì)象都會(huì)在內(nèi)部引用一個(gè)prototype的對(duì)象, prototype也會(huì)引用自己的原型對(duì)象, 以此類推, 鏈條的末尾是null為原型的對(duì)象, 當(dāng)一個(gè)對(duì)象引用了不屬于自己的屬性時(shí),將會(huì)遍歷原型鏈, 直到找到屬性,或者找到鏈尾 null
  • js中的對(duì)象和哈希表
    1. 對(duì)象本質(zhì)就是一個(gè)hash表, 即鍵值對(duì)的集合, 鍵總是字符串, 由于js是弱類型語言, 當(dāng)你傳入的鍵并非字符串時(shí)候, 也不會(huì)報(bào)錯(cuò), 而是隱式的使用toString()方法,
    2. 題目:
    var foo = new Object()
    var bar = new Object()
    var map = new Object()
    map[foo] = 'foo'
    map[bar] = 'bar'
    console.log(map[foo]) // logs: 'bar'
    解釋: 由于foo和bar都不是,字符串, js會(huì)隱式的將foo和bar使用toString()方法,由于它們都是空對(duì)象, 所以它們轉(zhuǎn)化的結(jié)果一樣: [Object Object], 也就是說map[bar]覆蓋了map[foo], map[foo]的結(jié)果也是覆蓋后的結(jié)果
    
  • 解釋js中的閉包, 什么是閉包, 它們有什么特性, 如何使用, 舉個(gè)例子
    1. 閉包是一個(gè)函數(shù), 包含在創(chuàng)建閉包時(shí)處于作用域內(nèi)的所有變量或其他函數(shù). 閉包通過'內(nèi)部函數(shù)'的形式實(shí)現(xiàn)的, 也就是另一個(gè)函數(shù)的主體內(nèi)定義函數(shù)
    2. 閉包的一個(gè)特性: 閉包可以一直訪問其包含函數(shù)的變量, 也就是說他們會(huì)一直存在在內(nèi)存中不被釋放
    3. 閉包可以防止變量被內(nèi)存釋放, for循環(huán)和閉包, 創(chuàng)建命名空間防止變量污染
  • 描述創(chuàng)建對(duì)象的不同方式, 和各自影響, 提供示例


    91527395499_.pic.jpg
  • 函數(shù)表達(dá)式(var foo = function (){})和函數(shù)語句(function foo(){})定義函數(shù)的區(qū)別?
    1. 函數(shù)語句可以在定義之前被調(diào)用(通過hoisting技術(shù), 總是使用函數(shù)的最后一個(gè)定義),
    function foo(){ return 1}
    console.log(foo()) // 結(jié)果為: 2
    function foo() {return 2}
    
    1. 函數(shù)表達(dá)式, 則不能在函數(shù)定義之前被調(diào)用
  • 將 js源文件里的內(nèi)容封裝到一個(gè)函數(shù)里, 這樣做的重要性和原因?
    1. 相當(dāng)于為它創(chuàng)建了一個(gè)閉包, 創(chuàng)建一個(gè)私有的命名空間,避免命名沖突
    2. 為全局變量提供一個(gè)容易引用的別名
    (function($){
       ...
    })(jQuery)
    
  • =====有什么區(qū)別, 舉個(gè)例子
    1. == 比較前會(huì)有隱式轉(zhuǎn)換, 而 ===是嚴(yán)格的類型比較
    2. 123 == '123'是成立的結(jié)果為true, 123 === '123'是不成立的, 結(jié)果為false
  • js文件開頭的use strict是什意思?
    1. js的嚴(yán)格模式, 對(duì)js代碼執(zhí)行嚴(yán)格的解析和錯(cuò)誤處理, 沒有直接調(diào)用者的函數(shù), this指向'undefined'

19 js中的this指向(非嚴(yán)格模式下)

函數(shù)中的this在函數(shù)被定義的時(shí)候并沒有確定下來, 只有函數(shù)被調(diào)用的時(shí)候,才知道它到底指向誰

  • 原則1: 一個(gè)函數(shù)沒有被上級(jí)調(diào)用, 那么this指向window
    function foo() {
      console.log(this) // window
    }
    foo()
    
  • 原則2: 一個(gè)函數(shù)被上級(jí)調(diào)用, 那么this指向上級(jí)函數(shù)
    var o = {
          a: 10,
          c: function() {
              console.log(this.a) // 10
              console.log(this) // o
          }
      }
    o.c()
    
  • 原則3: 一個(gè)函數(shù)中包含多個(gè)對(duì)象, 盡管這個(gè)函數(shù)是被最外層的對(duì)象調(diào)用, 但是this也只會(huì)指向它的上級(jí)
    var o = {
          a: 10,
          b: {
              a: 12,
              fn: function() {
                  console.log(this.a) // 12
                  console.log(this) // b
              }
          }
      }
    o.b.fn()
    
  • 原則4:
    var o = {
      a: 10,
      b: {
        a: 12,
        fn: function(){
          console.log(this.a) // undefined
          console.log(this) // window
        }
      }
    }
    var j = o.b.fn
    j() 
    
    • 原則5: 構(gòu)造函數(shù)中的this: new 可以改變對(duì)象的this指向 -> new后邊的函數(shù)
    function Fn() {
      this.user = 'zxk'
    }
    var a = new Fn()
    console.log(a.user) // 'zxk'
    
  • 原則6: this和return
    1. 構(gòu)造函數(shù)里return {}, this指向, 這個(gè)對(duì)象
    function Fn() {
          this.name = 'zxk'
          return {
              name: 'ret - zxk'
          }
      }
      var xx = new Fn()
      console.log(xx.name) // 'ret - zxk'
    
    1. 構(gòu)造函數(shù)里return function(){}, this指向, 這個(gè)函數(shù),但是沒有繼承這個(gè)函數(shù)的prototype, 打印出來的是空
     function Fn() {
          this.name = 'zxk'
          return function() {}
      }
      var xx = new Fn
      console.log(xx.name) // 啥也沒有
    
    1. 構(gòu)造函數(shù)里return 非對(duì)象, this指向原來的這個(gè)構(gòu)造函數(shù)
    function Fn() {
          this.name = 'zxk'
          return 1
      }
      var xx = new Fn()
      console.log(xx.name) // 'zxk'
    
  • call, apply和bind
    • 改變函數(shù)的this執(zhí)行, 并沒有繼承原型鏈
    • call, apply會(huì)立即執(zhí)行, bind需要()調(diào)用
  • 常用的字符串和數(shù)組方法:
    • slice(start, end): string直接返回重start開始到end(不包括start)的部分,可以為負(fù)
    • splice(index, howmany, item1, item2....,itemn): 從數(shù)組的index開始, 刪howmany個(gè)元素, 替換成item1 - itemn
    • concat() 合并兩個(gè)數(shù)組
    • substring(start, stop): 返回字符串start到stop(不包含)之間的字符, 不接受負(fù)值, 如果stop為負(fù)值, 那么就取start之前的值
    • substr(start, [length]): 返回字符串從start開始的, 共計(jì)length個(gè), 可以接受負(fù)值

20 js經(jīng)典面試題

// code 1
var length = 10;
function fn() {
  alert(this.length);
}
var obj = {
  length: 5,
  method: function() {
    fn();
  }
};
obj.method(); // 最后相當(dāng)于fn(), 函數(shù)沒有被任何上級(jí)調(diào)用, this指向window
// code 2
var num = 100;
var obj = {
  num: 200,
  inner: {
    num: 300,
    print: function() {
      console.log(this.num);
    }
  }
};

obj.inner.print(); //300, this指向inner

var func = obj.inner.print;
func(); //100 默認(rèn)綁定,this指向window

obj.inner.print(); //300 thi指向inner

(obj.inner.print = obj.inner.print)(); //100 this指向window
// code 3
function foo() {
  console.log(this.a);
}
var obj2 = { a: 42, foo: foo };
var obj1 = { a: 2, obj2: obj2 };
obj1.obj2.foo(); // 42 this指向他的直接上級(jí)obj2

var obj3 = { a: 2 };
foo.call(obj3); // 2, this指向call的參數(shù)obj3

var bar = function() {
  foo.call(obj3);
};
bar(); // 2, 就相當(dāng)于foo.call(obj3)
setTimeout(bar, 100); // 2, bar的this指向window, 但是執(zhí)行bar的時(shí)候, 其實(shí)執(zhí)行的是foo.cal(obj3), 
bar.call(window); // 2, 同上

var obj4 = { a: 3, foo: foo };
obj2.foo(); // 42, this指向obj2
obj4.foo(); // 3, this指向obj4
obj2.foo.call(obj4); // 3 this指向call的參數(shù)obj4
obj4.foo.call(obj2); // 42 this指向call參數(shù)obj2
// code 4
function foo() {
  console.log(this.a);
}
var obj = {
  a: 2,
  foo: foo
};
var a = "oops, global"; // a是全局對(duì)象的屬性
setTimeout(obj.foo, 100); // "oops, global", setTimeout里的this都會(huì)指向window, 相當(dāng)于var fun = obj.foo, fun()
obj.foo(); // 2, this指向obj

// code 5 (new綁定)
function foo(a) {
  this.a = a;
}
var bar = new foo(2);
console.log(bar.a); // 2 new可以改變this, 讓bar的this指向foo

var obj1 = { foo: foo };
var obj2 = {};

obj1.foo(2); 
console.log(obj1.a); // 2, foo(2)的this指向obj1, this.a相當(dāng)于給obj1添加a屬性

obj1.foo.call(obj2, 3);
console.log(obj2.a); // 3,  obj1的this指向obj2并傳參數(shù), 相當(dāng)于給obj2, 添加a屬性

var bar = new obj1.foo(4);
console.log(obj1.a); // 2
console.log(bar.a); // 4 

// code 6

function foo() {
  console.log(this.a);
}

var a = 2;

// 如果你把null或者undefined作為this的綁定對(duì)象傳入call\apply\bind,這些值在調(diào)用的時(shí)候會(huì)被忽略,實(shí)際應(yīng)用的是默認(rèn)綁定規(guī)則。
foo.call(null); // 2
var bar = foo.bind(null);
bar(); // 2
foo.apply(undefined); // 2

// code 7 箭頭函數(shù)

function foo() {
  return a => console.log(this.a);
}

var obj1 = { a: 2 };
var obj2 = { a: 3 };
var bar = foo.call(obj1);
bar.call(obj2); // 2 箭頭函數(shù)是根據(jù)外層(函數(shù)或者全局)作用域來決定this。并且綁定后無法修改。
    1. 字符串倒序
    function reverseString(str) {
      var strArray = str.split(""); // 使用空字符串來分割成字符數(shù)組
      return strArray.reverse().join(""); // 反轉(zhuǎn)并連接
    }
    reverseString("hello");
    
    1. 下面代碼執(zhí)行結(jié)果是啥, 如何實(shí)現(xiàn)每隔1秒輸出1 - 5
    for (var i = 1; i <= 5; i++) {
      setTimeout(function() {
        console.log(i);
      }, i * 1000);
    }
    

    每個(gè)1秒秒輸出6共輸出5個(gè), 循環(huán)終止條件是i <= 5, i最終值是6的時(shí)候, 循環(huán)才結(jié)束, setTimeout會(huì)把函數(shù)踢出本次任務(wù)隊(duì)列, 等循環(huán)結(jié)束后, 才打印console.log(i), i那個(gè)時(shí)候已經(jīng)是6了,

    • 套個(gè)閉包, 并把每次循環(huán)的i緩存起來,并傳進(jìn)閉包就ok
    • 用let聲明 變量: 每次循環(huán)都會(huì)重新聲明一個(gè)i
    for(let i = 0; i < 5; i++) {
          setTimeout(function() {
              console.log(i)
          }, i*1000)
      }
    
    1. 代碼執(zhí)行結(jié)果
    3 + "3" // '33'
    "23" > "3" // false
    var b = true && 2; // undefined
    "abc123".slice(2, -1) // 'c12'
    "abc123".substring(2, -1) // 'ab' //如果 start or stop 是負(fù)數(shù)或 NaN,會(huì)把它當(dāng)成 0 對(duì)待;如果 start > stop,則會(huì)交換這兩個(gè)參數(shù)
    
 var foo = 1,
 bar = 2,
 j,
 test;
test = function(j) {
 j = 5;
 var bar = 5;
 console.log(bar); // 5
 foo = 5;
};
test(10);
console.log(foo); // 5 改變的全局變量
console.log(bar); // 2 由于函數(shù)作用域?qū)θ肿饔糜虻碾[藏,所以只有在test函數(shù)內(nèi)部,bar=5,并不能影響到全局中的bar
console.log(j); // undefined  test(10)函數(shù)調(diào)用的時(shí)候,是函數(shù)內(nèi)部的參數(shù)j接收到了10,但是它也是函數(shù)作用域內(nèi)的變量,并不會(huì)改變?nèi)肿饔糜蛑械膉。
if (!("sina" in window)) {
  var sina = 1;
}
console.log("sina:", sina); // undefined
// 變量提升: js會(huì)把所有的通過var聲明的全局變量, 提升到最頂層,  所有sina液在if之前就存在了, 也不會(huì)走if()分支
// 相當(dāng)于
var sina
f (!("sina" in window)) {
   sina = 1;
}
console.log("sina:", sina); // undefined
function SINA() {
  return 1;
}
var SINA;
console.log(typeof SINA); // function
// 重復(fù)聲明被忽略了, 所以var沒有生效
  • 數(shù)組去重, 帶obj的元素
var arr = [2, [1,2], 3, "2", "a", "b", "a", [1, 2]]
  function quchong(arr) {
      var map = {}
      var res = []
      arr.forEach(item => {
          if(!map[JSON.stringify(item)]) {
              res.push(item)
              map[JSON.stringify(item)] = 1
          }
      })
      return res
  }
  console.log(quchong(arr))
function foo() {
  "use strict";
  console.log(this.a);
}

function bar() {
  console.log(this.a);
}

var a = "this is a 'a'";

bar(); // "this is a 'a'"
foo(); // "TypeError: Cannot read property 'a' of undefined
alert(a); // 輸出函數(shù)體
a(); // 10
var a = 3;
function a() {
  alert(10);
}
alert(a); // 3
a = 6;
a(); // 報(bào)錯(cuò)a不是一個(gè)function
alert(a); // undefined
a(); // a is not a function
var a = 3;
var a = function() {
  // 函數(shù)表達(dá)式
  alert(10);
};
alert(a); // 輸出函數(shù)體
a = 6;
a(); // a is not a function 因?yàn)閍已經(jīng)賦值成6了
  • 查看字符串中最多的元素
function findMax(str) {
      var map = {} // 存儲(chǔ)str每個(gè)元素和對(duì)應(yīng)數(shù)量的對(duì)象
      var max = {num: 0} // 存儲(chǔ)最大值的對(duì)象
      for(var i in str) {
          if(map[str[i]]) {
              map[str[i]] ++
          } else {
              map[str[i]] = 1
          }
          if(map[str[i]] > max.num) {
              max.num = map[str[i]]
              max.key = str[i]
          }
      }
      return max
  }
  var max = findMax(_str)
  console.log(max)

21 數(shù)組方法和字符串方法

  • 數(shù)組方法:
    • pop(): 刪除數(shù)組最后刪一個(gè)元素, 并返回這個(gè)元素
    • push(): 在數(shù)組末尾添加一個(gè)元素, 并返回?cái)?shù)組的length
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容