JS高級與面向?qū)ο?/h1>

一锋八、JavaScript基礎(chǔ)知識回顧

1.1 JavaScript

1.1.1 javascript是什么鳄逾?

JavaScript是一門編程語言蝎抽,用來操作頁面標簽和樣式。

1.1.2 javascript的組成

  • ECMAScript:可以為不同種類的宿主環(huán)境提供核心的腳本編程能力缚去,因此核心的腳本語言是與任何特定的宿
    主環(huán)境分開進行規(guī)定的潮秘。Web 瀏覽器對于 ECMAScript 來說是一個宿主環(huán)境,但它并不是唯一的宿主環(huán)境易结。
    ECMAScript描述了以下內(nèi)容:語法枕荞、類型搞动、語句躏精、關(guān)鍵字、保留字鹦肿、運算符矗烛、對象。
  • DOM:(Document Object Model 文檔對象模型)是 HTML 和 XML 的應用程序接口(API)箩溃。DOM 將把
    整個頁面規(guī)劃成由節(jié)點層級構(gòu)成的文檔瞭吃。HTML 或 XML 頁面的每個部分都是一個節(jié)點的衍生物。用 DOM
    API 可以輕松地刪除涣旨、添加和替換節(jié)點歪架。
  • BOM:(Browser Object Model 瀏覽器對象模型)可以對瀏覽器窗口進行訪問和操作。

1.1.3 ECMAScript與JavaScript的關(guān)系

前者是后者的規(guī)格霹陡,后者是前者的一種實現(xiàn)和蚪。

1.1.4 JavaScript中的數(shù)據(jù)類型

  • 基本類型:number string boolean null undefined
  • 引用類型:object (Array Date Math(比較特別) RegExp Function Object Error Number String Boolean XMLHttpRequest )
  • 基本類型與引用類型的差別:
    • 存儲方式不同:基本類型數(shù)據(jù)存儲在棧stack;引用類型存儲在堆heap穆律。
    • 賦值方式不同:基本類型賦值的時候傳遞的是具體的值惠呼;引用類型賦值的時候傳遞的是內(nèi)存的地址。

1.1.5 JavaScript中的語句

  • 分支:if,if else,switch
  • 循環(huán):do while,while,for,for in

1.2 異常處理

作用:

  • 防止某些程序出錯時影響后面代碼的執(zhí)行峦耘。
  • 屏蔽底層的報錯細節(jié),從而給用戶一個友好提示旅薄。
var abc = 123;
try{
    var data = false;
    if(!false){
        throw new Error('數(shù)據(jù)格式異常');
    }
    //try當中的代碼一旦發(fā)生錯誤辅髓,try當中之后的代碼就不再執(zhí)行了
    console.log(abc);
}catch(e){
    //只有try當中的代碼發(fā)生錯誤泣崩,這里才會執(zhí)行
    console.log(e.message);//表示錯誤原因
    console.log(e.name);//表示錯誤類型
}finally{
    //無論try當中的代碼是否執(zhí)行,這里都會執(zhí)行
    console.log(abc);
}

二洛口、面向?qū)ο?/h2>

2.1 面向?qū)ο蟾攀?/h3>

2.1.1 什么是對象

所謂的對象就是某種事物矫付,萬物皆對象。

用程序的方式描述對象:屬性+行為第焰。

2.1.2 對象創(chuàng)建方式

  • 字面量:各種數(shù)據(jù)類型的字面量表示买优。

    var obj1 = {
      username : '張三',
      age : 12,
      gender : 'male'
    };
    
  • 構(gòu)造函數(shù):內(nèi)置對象和自定義對象。

    var obj2 = new Object();
    obj2.username = '李四';
    obj2.age = 13;
    obj2.gender = 'female';
    

    如果構(gòu)造函數(shù)不需要傳遞參數(shù)挺举,那么后面的括號可以省略杀赢。

    var obj = new Object();
    var obj = new Object;
    

2.1.3 屬性的訪問方式

  • 對象名.屬性名稱
  • 對象名['屬性名稱']湘纵。

兩種方式的區(qū)別:方括號的方式可以使用變量脂崔。

2.1.4 實例化的本質(zhì)

構(gòu)造函數(shù)實例化對象本質(zhì)上做了什么工作?

  1. 開辟堆內(nèi)存用來存儲實例中數(shù)據(jù)(屬性和方法)梧喷。
  2. 用this指向該區(qū)域砌左。
  3. 通過this向該區(qū)域中放置數(shù)據(jù)。
  4. 返回this
function Foo(info){
        // 構(gòu)造函數(shù)中的this指的是構(gòu)造函數(shù)所創(chuàng)建的實例對象
        this.info = info;
        this.showInfo = function(){
            // 實例方法中的this指向方法的調(diào)用者(實例對象本身)
            console.log(this.info);
        }
        // 構(gòu)造函數(shù)的默認返回值就是this
    }
    var foo = new Foo('tom');
    foo.showInfo();

    var foo1 = new Foo('jerry');
    foo1.showInfo();

2.1.5 構(gòu)造函數(shù)的返回值

  • 構(gòu)造函數(shù)如果顯示的返回基本數(shù)據(jù)類型铺敌,那么和不返回等效汇歹。
  • 構(gòu)造函數(shù)如果顯示的返回引用數(shù)據(jù)類型,那么就以此為準偿凭,就不再返回默認的this了秤朗。
function Person(name){
    this.name = name;
    return 123;         //輸出:Person {name: "zhangsan"}
    return 'hello';     //輸出:Person {name: "zhangsan"}

    return {
        name : 'lisi',
        age : 12
    };                  //輸出:Object {name: "lisi", age: 12}
    return [1,2,3];     //輸出:[1,2,3]
}
var p = new Person('zhangsan');
console.log(p);

2.1.6 對象原型

JavaScript中對象的本質(zhì):無序的鍵值對集合。

原型:實現(xiàn)數(shù)據(jù)共享(實例對象之間進行數(shù)據(jù)共享)笔喉。

function Foo(info){
this.info = info;
this.showInfo = function(){
console.log(this.info);
}
}
var f1 = new Foo('tom');
var f2 = new Foo('jerry');
console.log(f1.showInfo === f2.showInfo);//false
-------------------------------------------------------------------------------
function fn(){
    console.log(this.name);
}
function Person(name,age){
    this.name = name;
    this.age = age;
    this.showName = fn;
}
var p1 = new Person('zhangsan');
var p2 = new Person('lisi');
console.log(p1.showName === p2.showName);//true

2.1.7 原型分析

原型:函數(shù)都有一個原型屬性prototype取视,該屬性值本質(zhì)上也是對象(實際就是Object的實例)。

原型的作用:實現(xiàn)數(shù)據(jù)共享(實例對象之間進行共享)常挚;實現(xiàn)繼承作谭。

__proto__:構(gòu)造函數(shù)產(chǎn)生的實例對象都有一個屬性__proto__,該屬性不是標準屬性奄毡,不可以在編程中使用折欠,實際上該屬性是瀏覽器內(nèi)部使用的,該屬性和構(gòu)造函數(shù)中的prototype指向相同吼过。

__proto__屬性在實例對象中锐秦,prototype屬性在構(gòu)造函數(shù)中,這兩個屬性的指向是相同的盗忱。

function Person(name,age){
    this.name = name;
    this.age = age;
}

Person.prototype.showName = function(){
    console.log(this.name);
}
Person.prototype.showAge = function(){
    console.log(this.age);
}
Person.prototype.flag = 123;
Person.prototype.arr = ['red','green','blue'];

var p1 = new Person('tom',12);
p1.flag = 456;
p1.arr.push('pink');
var p2 = new Person('jerry',13);

console.log(p1.flag,p2.flag);   //456 123
console.log(p1.arr,p2.arr);     //["red", "green", "blue", "pink"] ["red", "green", "blue", "pink"]

//解釋:
//通過對象.屬性名稱=值  這種做法會向?qū)ο笾刑砑右粋€屬性
//但是obj.arr.push(123); 這種結(jié)構(gòu)不會再obj中添加屬性酱床,而會obj.arr數(shù)組中添加一項數(shù)據(jù)

2.2 面向過程與面向?qū)ο?/h3>

2.2.1 相關(guān)概念

  • 面向?qū)ο笫且环N編程模式,就是以對象的方式寫代碼趟佃。

    三大特性:封裝扇谣、繼承那個昧捷、多態(tài)。

  • 面向過程的編程模式的缺點:團隊開發(fā)容易產(chǎn)生命名沖突罐寨;不方便代碼的重用靡挥;可維護性差。

  • JavaScript面向?qū)ο笙嚓P(guān)概念:

    1. 構(gòu)造函數(shù)
    2. 實例對象
    3. 原型

2.2.2 面向?qū)ο箝_發(fā)

//實現(xiàn)如下功能:點擊一個按鈕改變div的背景色
//用面向?qū)ο蟮娘L格封裝(構(gòu)造函數(shù)+原型)

function ChangeColor(btnId,divId){
    this.btn = document.getElementById(btnId);
    this.div = document.getElementById(divId);
}

ChangeColor.prototype.init = function(){
    // 原型方法中的this指的是該原型所屬的構(gòu)造函數(shù)的實例化對象鸯绿,實際上與構(gòu)造函數(shù)中的this指向相同
    var that = this;//緩存實例對象
    this.btn.onclick = function(){
        // 這里的this是綁定事件函數(shù)的DOM對象
        that.div.style.backgroundColor = 'yellow';
    }
}

onload = function(){
    var cc = new ChangeColor('btn','div1');
    cc.init();
}

//不同的this場景:
//1跋破、構(gòu)造函數(shù)中的this
//2、原型方法中的this
//3瓶蝴、事件方法中的this

//1) 構(gòu)造函數(shù)中的this和原型方法中的this指向相同:都是指向?qū)嵗龑ο?//2)事件方法中的this指的是綁定事件的對象

2.2.3 對象中屬性的判斷

  • in:判斷對象中是否存在某個屬性(屬性在實例對象和原型對象都可以)毒返。
  • hasOwnProperty():判斷屬性是否在實例對象上。
//小測試:
if('a' in window) {
    var a = 123
    console.log(a);
}
//輸出:123
//考點:
//1.全局作用域中的變量和函數(shù)都是window對象的成員
//2.預解析
//3.js中沒有塊級作用域
//實現(xiàn)一份方法囊蓝,判斷某個屬性是否在原型上
function check(attr,obj){
    if(attr in obj && !obj.hasOwnProperty(attr)){
        return true;
    }else{
        return false;
    }
}

2.3 構(gòu)造函數(shù)退渗、原型與實例的關(guān)系

2.3.1 構(gòu)造函數(shù)诫睬、原型與實例的關(guān)系

  1. 構(gòu)造函數(shù)中都有原型屬性prototype狸膏,該屬性值本質(zhì)也是對象(Object的實例對象)
  2. 原型對象中都有一個屬性constructor微宝,該屬性指向原型所屬的構(gòu)造函數(shù)
  3. 實例對象中都有一個屬性__proto__,該屬性不是標準屬性蝎宇,不可以在編程中使用弟劲,實際上是瀏覽器內(nèi)部使用的,并且該屬性指向原型對象姥芥。

2.3.2 原型鏈

  • 原型鏈:實例對象和原型對象之間形成的有限鏈式結(jié)構(gòu)兔乞,該鏈式結(jié)構(gòu)通過__proto__連接起來,用于實現(xiàn)繼承和共享屬性凉唐。

  • 對象是有原型對象的庸追,原型對象也有原型對象,原型對象也有原型對象台囱,對象的原型對象一直往上找淡溯,會找到一個null。

    var obj = new Object();
    // obj -> Object.prototype -> null
    
    var arr = new Array();
    // arr -> Array.prototype -> Object.prototype -> null
    
    var date = new Date();
    // date -> Date.prototype -> Object.prototype -> null
    
  • 原型鏈的結(jié)構(gòu)可以通過重置原型對象的方式來修改簿训。

    function Foo1(info){
        this.info = info;
    }
    Foo2.prototype = new Foo1('tom');
    //Foo2.prototype.constructor = Foo1;
    function Foo2(info){
        this.info = info;
    }
    Foo3.prototype = new Foo2('jerry');
    //Foo3.prototype.constructor = Foo2;
    function Foo3(info){
        this.info = info;
    }
    var f = new Foo3('spike');
    console.dir(f);
    
    // f -> new Foo2('jerry') -> new Foo1('tom') -> Foo1.prototype -> Object.prototype -> null
    

2.4 繼承

繼承:別人的拿過來咱娶,自己的還是自己的∏科罚可以通過修改原型的指向來實現(xiàn)膘侮。

2.4.1 原型繼承

function Animal() {
    this.name = '動物';
}

function Tiger(color) {
    this.color = color;
}
Tiger.prototype = new Animal();
var tiger = new Tiger('黃色');
console.log(tiger.name);
console.log(tiger.color);

缺點:沒有辦法給基礎(chǔ)過來的屬性賦值,而不影響所有的實例的榛。繼承過來的引用類型的數(shù)據(jù)琼了,所有的實例時共享的。

2.4.2 借用構(gòu)造函數(shù)繼承

  • call和apply的基本使用:

    1. call和apply可以調(diào)用函數(shù)困曙。
    2. 改變所調(diào)用函數(shù)內(nèi)部的this指向表伦。
    3. 在非嚴格模式下谦去,普通函數(shù)中this是window慷丽;在嚴格模式下蹦哼,普通函數(shù)中this是undefined。
  • 借用構(gòu)造函數(shù)繼承:

    function Person(name,favour){
        this.name = name;
        this.favour = favour;
    }
    
    Person.prototype.showName = function(){
        console.log(this.name);
    }
    
    function Student(num,name,favour){
        // 這里的this是Student構(gòu)造函數(shù)的實例
        // Person.call(this,name,favour);
        Person.apply(this,[name,favour]);
        this.num = num;
    }
    
    var stu1 = new Student(1,'zhangsan',['coding']);
    stu1.favour.push('swimming');
    var stu2 = new Student(2,'lisi',['dancing']);
    
    console.dir(stu1);
    console.dir(stu2);
    stu1.showName();
    

    缺點:沒有辦法繼承父級構(gòu)造函數(shù)原型上的成員要糊。

2.4.3 組合繼承

function Person(name,age){
    this.name = name;
    this.age = age;
}
Person.prototype.show=function(){
    console.log(this.name+"今年"+this.age+"歲了");
}
Person.prototype.flag=1;

function Teacher(name,age,level){
    Person.call(this,name,age);
    this.level=level;
}
Teacher.prototype=new Person();

var t1 = new Teacher("張三",33,"T5");
var t2 = new Teacher("李四",30,"T4");
t1.show();

2.5 Object.create的基本使用

//ES5新特性纲熏,方法的作用:創(chuàng)建對象
var create = function(obj){
    if(Object.create){
        return Object.create(obj);
    }else{
        function F(){}
        F.prototype = obj;
        return new F();
    }
}

2.6 屬性的復制

2.6.1 淺拷貝

var obj = {};
var obj1 = {
    username : 'zhangsan',
    age : 12,
    gender : 'male'
}
function extend(des,origin){
    for(var key in origin){
        des[key] = origin[key];
    }
}
extend(obj,obj1);
console.log(obj);

2.6.2 深拷貝

function foo(set){
    var defaultSettings = {
        width : '100',
        height : '200',
        backgroundColor : 'gray',
        sets : {
            flag : 12,
            abc : 'message'
        }
    }
    var obj = {
        www : 'www'
    }
    var obj1 = {
        qqq : 'qqq'
    }
    $.extend(true,defaultSettings,set,obj,obj1);
    console.dir(defaultSettings);
    console.log(defaultSettings.width);
    console.log(defaultSettings.sets.flag);
    console.log(defaultSettings.sets.abc);
}

var settings = {
    width : '1000',
    sets : {
        flag : 123,
    }
}
foo(settings);

2.7 函數(shù)

2.7.1 函數(shù)的原型鏈

  • Function
    1. 所有的函數(shù)都是Function的實例。
    2. Funciton也是一個函數(shù)锄俄。

2.7.2 函數(shù)的三種角色

  1. 構(gòu)造函數(shù)
  2. 普通函數(shù)
  3. 函數(shù)作為對象
function Foo(){}
var foo = new Foo();    //構(gòu)造函數(shù)
Foo();                  //普通函數(shù)
Foo.info = 'hello';     //函數(shù)作為對象

函數(shù)到底是哪種角色局劲,取決于函數(shù)的調(diào)用方式

2.7.3 函數(shù)的定義方式

  • 系統(tǒng)函數(shù)(類庫、庫函數(shù))

  • 自定義函數(shù)

    1. 函數(shù)聲明

      function foo(){
         console.log(123);
      }
      
    2. 函數(shù)表達式

      var fn = function(){
          console.log(456);
      }
      fn();
      
    3. new Function()

      var fn1 = new Function('console.log(789);');//需要把字符串轉(zhuǎn)成js代碼并執(zhí)行奶赠,性能沒有前兩者好
      fn1();
      

    區(qū)別

    1. 函數(shù)聲明是在預解析階段創(chuàng)建的鱼填,而函數(shù)表達式是在程序執(zhí)行階段創(chuàng)建的。
    2. 函數(shù)聲明只能在全局或者函數(shù)內(nèi)部定義毅戈,而函數(shù)表達式只能在表達式中定義苹丸。
  • 函數(shù)都是對象,但對象不一定是函數(shù)苇经。

  • Math不是函數(shù)赘理,而是對象

2.7.4 this的不同指向場景

  • 函數(shù)的調(diào)用方式:(函數(shù)中的this指向取決與函數(shù)的調(diào)用方式)

    1. 構(gòu)造函數(shù)
    2. 普通函數(shù)
    3. 對象方法
    4. call和apply調(diào)用(bind)
  • this的不同指向:

    1. 構(gòu)造函數(shù)中的this指向?qū)嵗龑ο?/li>
    2. 原型方法中的this指向?qū)嵗龑ο螅c構(gòu)造函數(shù)中的this指向相同
    3. 在非嚴格模式下扇单,普通函數(shù)中的this指向window商模,在嚴格模式下,普通函數(shù)中的this指向undefined
    4. 對象方法中的this就是調(diào)用方法的對象
    5. 事件方法中的this指的是綁定事件的對象
    6. 定時函數(shù)中的this指的是window
    7. call或apply所調(diào)用的函數(shù)中的this就是call或apply中的第一個參數(shù)(該參數(shù)必須是引用類型)
  • bind的基本用法:

    • bind方法是ES5的新特性(函數(shù)的柯里化)
    • bind用來改變函數(shù)內(nèi)部的this指向蜘澜,但是不調(diào)用函數(shù)施流,并且bind會返回一個新函數(shù)(其實還是原來的函數(shù)內(nèi)容,只是this改變?yōu)閎ind中的第一個參數(shù)鄙信,該參數(shù)必須為引用類型)
    var inner = function(a,b){
        console.log(a+b);
    }
    var newInner = inner.bind({info:'hello'},12,13);
    setTimeout(newInner,1000);
    

2.7.5 高階函數(shù)

高階函數(shù)

  • 作為參數(shù)的函數(shù)

    function foo(fn) {
      var data = {
          info: 'hello'
      }
      fn(data);
    }
    var fn = function(data) {
      console.log(data.info);
    };
    foo(fn);
    
  • 作為返回值的函數(shù)(閉包)

    function foo(){
      var num = 1;
      return function(){
          return num++;
      }
    }
    var fn = foo();
    var r1 = fn();
    var r2 = fn();
    console.log(r1,r2);
    

2.8 對象加深

2.8.1 對象的體系結(jié)構(gòu)

  1. 所有的實例對象都有一個__proto__屬性瞪醋,該屬性指向產(chǎn)生實例對象的構(gòu)造函數(shù)的原型。
  2. 所有的構(gòu)造函數(shù)都有一個prototype屬性扮碧,該屬性本質(zhì)上也是一個對象(Object的實例對象)
  3. 所有的原型對象都有一個constructor屬性趟章,該屬性指向原型所屬的構(gòu)造函數(shù)。
  4. 原型對象中有一個__proto__屬性慎王,該屬性指向Object.prototype(Object的原型對象中沒有__proto__蚓土,因為這里就是原型鏈的終點)
  5. 所有的函數(shù)都是Function的實例對象。
  6. Function函數(shù)本身也是它自己的實例對象(也就是Function.__proto__===Function.prototype)

2.8.2 基本類型與引用類型深入理解

  • 基本類型

    var num = 123
    function foo(data){
      data = '456';
      return data;
    }
    var ret = foo(num);
    console.log(ret,num);//456 123
    
  • 引用類型

    var arr = [1,2,3];
    function foo(data){
      data.push(4);
      return data;
    }
    var ret = foo(arr);
    console.log(ret,arr);//[1, 2, 3, 4] [1, 2, 3, 4]
    

2.8.3 標準庫

  • 常用對象:Object赖淤、Array蜀漆、Date、RegExp咱旱、Math确丢、Function绷耍、Error
  • 包裝對象:Number、String鲜侥、Boolean

2.8.4 類數(shù)組(關(guān)聯(lián)數(shù)組)詳解

  • 類數(shù)組:

    var obj = {
      0 : 'qqq',
      1 : 'www',
      2 : 'eee',
      length : 3
    }
    
  • 類數(shù)組轉(zhuǎn)數(shù)組:

    var arr = [].slice.call(obj,0);
    
  • delete的用法:

    var obj = {
      info : 'abc',
      username : 'lisi'
    }
    delete obj.info;
    console.log(obj);//Object {username: "lisi"}
    var flag = 123;
    delete flag;
    console.log(flag);//123
    
    1. delete的作用就是刪除對象的屬性褂始。
    2. 全局作用域中var聲明的變量,delete無法刪除描函,但是不用var聲明的全局變量可以delete刪除崎苗。
  • 求數(shù)組中的最大值:

    //排序
    var arr = [12321,234,99999999,4454,12,454545,343,34,342];
    arr.sort(function(a,b){
        return b - a;
    });
    console.log(arr);//[99999999, 454545, 12321, 4454, 343, 342, 234, 34, 12]
    
    //對象中的Math方法
    var max = Math.max(123,23,4324,45,4,645,6,45645);
    console.log(max);
    
    //借用對象的方法
    var max = Math.max.apply(null,arr);
    console.log(max);
    

    call和apply的應用場景

    1. 調(diào)用函數(shù)
    2. 改變所調(diào)用函數(shù)的內(nèi)部this指向
    3. 轉(zhuǎn)換類數(shù)組
    4. 借用別的對象方法

2.9 遞歸

2.9.1 遞歸的執(zhí)行原理

function fn(n){
    if(n == 1){
        console.log('遞歸結(jié)束' + n);
        return 1;
    }else{
        console.log('遞歸前' + n);
        var ret = n * fn(n-1);
        console.log('遞歸后' + n);
        return ret;
    }
}
var ret = fn(5);
console.log(ret);

/* 輸出結(jié)果:
遞歸前5
遞歸前4
遞歸前3
遞歸前2
遞歸結(jié)束1
遞歸后2
遞歸后3
遞歸后4
遞歸后5
120
*/

2.9.2 遞歸的應用

function getChildNodes(node, arr) {
    for (var i = 0; i < node.childNodes.length; i++) {
        var subNode = node.childNodes[i];
        //如果子節(jié)點是元素類型就放到數(shù)組中
        if (subNode.nodeType == 1) {
            arr.push(subNode);
            //以當前子節(jié)點作為新的父節(jié)點繼續(xù)遞歸
            getChildNodes(subNode, arr);
        }
    }
}
window.onload = function () {
    var arr = [];
    var div = document.getElementById('div');
    getChildNodes(div, arr);
    console.log(arr);
}

2.9.3 jQuery實例化過程

$(function(){
        // var ret = $('.active');
        // console.dir(ret);
        // ret.html('123').css('backgroundColor','green');

        // var aDiv = document.getElementsByTagName('div')[0];
        // console.dir(aDiv);

        // // ret[0];
        // console.log(ret.get(0) === aDiv);

        function jQuery(selector){
           return new jQuery.prototype.init(selector);
        }
        jQuery.prototype = {
            constructor : jQuery,
            html : function(){
                console.log(123);
                return this;
            },
            css : function(){
                console.log(456);
                return this;
            },
            init : function(selector){
                // 實現(xiàn)選擇器功能
                // div .active #div1  div span  .active div span
                // Sizzle
                var aDiv = document.getElementsByTagName(selector);
                // 把每一個div都放到this中,那么this就是一個類數(shù)組
                [].push.apply(this,aDiv);
                this.length = aDiv.length;
            }
        }
        jQuery.prototype.init.prototype = jQuery.prototype;

        var obj = jQuery('div');
        obj.html('123').css(456);

        // obj.html('hello').css();
        $('div').css('width');//獲取某個樣式值
        $('div').css('width','100px');//設(shè)置樣式值
        $('div').css({
            width : '100px',
            height : '100px'
        });
        $('div').css(['width','height']);//{width : 100px,height : 100px}


    });
//待整理

2.10 作用域與閉包

2.10.1 作用域

作用域:指的是變量的作用范圍舀寓。

  • 全局作用域
  • 函數(shù)作用域
  • js沒有塊級作用域

作用域鏈:鏈是一個對象列表(list of objects) 胆数,用以檢索上下文代碼中出現(xiàn)的標識符(identifiers) 。標示符可以理解為變量名稱互墓、函數(shù)聲明和普通參數(shù)必尼。作用域鏈包括活動對象和父級變量對象。

  • 函數(shù)內(nèi)層作用域可以訪問外層作用篡撵,但是反過來不可以判莉。

2.10.2 預解析

JavaScript解析器在執(zhí)行代碼的時候分為兩個階段:

  1. 預解析
    • 全局預解析(所有的變量和函數(shù)聲明都會提前;同名的函數(shù)和變量函數(shù)的優(yōu)先級高)
    • 函數(shù)內(nèi)部預解析(所有的變量酸休、函數(shù)和形參都會預解析骂租,優(yōu)先級:函數(shù) > 形參 > 變量)
  2. 從上到下逐行執(zhí)行

先預解析全局作用域,然后執(zhí)行全局作用域中的代碼斑司,在執(zhí)行全局代碼的過程中遇到函數(shù)調(diào)用就會先進行函數(shù)預解析渗饮,然后再執(zhí)行函數(shù)內(nèi)的代碼。

2.10.3 閉包

閉包是一系列代碼塊(在ECMAScript中是函數(shù))宿刮,并且靜態(tài)保存所有父級的作用域互站。通過這些保存的作用域來搜尋到函數(shù)中的自由變量。

當一個函數(shù)在自身函數(shù)體內(nèi)需要引用一個變量僵缺,但是這個變量并沒有在函數(shù)內(nèi)部聲明(或者也不是某個參數(shù)名)胡桃,那么這個變量就可以稱為自由變量[free variable]。

閉包

  • 封閉的區(qū)域
  • 函數(shù)的嵌套形成閉包(內(nèi)層函數(shù)和內(nèi)層函數(shù)所處的作用域)
  • 閉包可以操作函數(shù)內(nèi)部的變量(間接的)

閉包的作用

  • 可以緩存中間狀態(tài)值
  • 延長變量的生命周期
var arr = [];
for (var i = 0; i < 3; i++) {
    arr[i] = (function(num){
        return function(){
            console.log(num);
        }
    })(i);
}
arr[0]();   //0
arr[1]();   //1
arr[2]();   //2

閉包的應用

onload = function(){
    var aInput = document.getElementsByTagName('input');
    for (var i = 0; i < aInput.length; i++) {
        // aInput[i].onclick = (function(){
        //     var num = 0;
        //     return function(){
        //         ++num;
        //         console.log(num);
        //     }
        // })();
        aInput[i].onclick = function(){
            this.num?++this.num:this.num=1;
            console.log(this.num);
            console.dir(this);
        }
    }
}

2.10.4 對象排序

function sortFn(sortName){
    return function(a,b){
        var v1 = a[sortName];
        var v2 = b[sortName];
        if(v1 > v2){
            return 1;
        }else if(v1 < v2){
            return -1;
        }else{
            return 0;
        }
    }
}

2.11 事件

2.11.1 函數(shù)相關(guān)屬性補充

  • arguments 表示實參的集合
  • length 形參的個數(shù)
  • caller 函數(shù)的調(diào)用者
  • name 函數(shù)的名稱
  • arguments.callee 表示函數(shù)本身磕潮,但是不推薦使用

2.11.2 事件處理機制

  • 瀏覽器本身是單線程還是多線程翠胰?多線程(多進程)
    1. 頁面標簽的渲染
    2. 網(wǎng)絡(luò)通信
    3. 解析js的運行
  • js的運行是單線程的
  • 事件隊列(隊列中放什么?任務(wù)(實際上就是函數(shù)))
    1. 定時函數(shù)(延時時間到了)
    2. 事件函數(shù)(對應的事件觸發(fā))
    3. Ajax的回調(diào)函數(shù)(接收到服務(wù)器完整的數(shù)據(jù)(readyState值發(fā)生變化的時候))
  • 事件隊列中任務(wù)執(zhí)行的條件:
    1. 主線程空閑
    2. 滿足任務(wù)的觸發(fā)條件

2.11.3 事件綁定方式

  • 行內(nèi)綁定

    <div onclick="fn3();">
        <div onclick="fn2();">
            <div onclick="fn1();">點擊</div>
        </div>
    </div> 
    
  • 給DOM元素直接綁定 btn.onclick

    div.onclick = function(){
      console.log(1);
    }
    
  • addEventListener / attachEvent

    div.addEventListener('click',function(){
      console.log(11);
    },false)
    

2.11.4 阻止冒泡與阻止默認行為

  • 在原生js中自脯,return false只能阻止默認行為之景,不能阻止冒泡;只能阻止btn.onclick這種方式綁定的事件膏潮,不能阻止addEventListener綁定的事件锻狗。
  • 在jQuery中,return false既可以阻止冒泡也可以阻止默認行為。

2.11.5 自定義事件

  • 注冊事件

    function addEvent(obj,type,fn){
        obj.arrs = obj.arrs || {};
        obj.arrs[type] = obj.arrs[type] || [];
        obj.arrs[type].push(fn);
    }
    var obj = {};
    addEvent(obj,'abc',function(){
        console.log('abc');
    });
    addEvent(obj,'abc',function(){
        console.log('abc1');
    });
    addEvent(obj,'hi',function(){
        console.log('hi');
    });
    
  • 觸發(fā)事件

    function fireEvent(obj,type){
        var fnList = obj.arrs[type];
        for (var i = 0; i < fnList.length; i++) {
            fnList[i]();
        }
    }
    fireEvent(obj,'hi');
    

2.12 正則

2.12.1 正則相關(guān)API

  • 正則的API:

    1. test

      var reg = /\d/;
      console.log(reg.test('123'));
      
    2. exec

      var str = 'adsfasdf123asdfasdf21312sfdsadfad';
      var reg = /\d+/g;
      // var ret = reg.exec(str);
      // console.log(ret);
      var result = null;
      while((result = reg.exec(str)) != null) {
          console.log("Matched `" + result[0] +
                "' at position " + result.index +
                " next search begins at position " + reg.lastIndex);
      }
      
  • 字符串API:

    1. search:查詢匹配字符串的索引

      var str = 'dsdaf123asdfasdf';
      console.log(str.search('123'));
      console.log(str.search(/\d+/));
      
    2. match

      //從字符串中找出數(shù)字
      var str = '1212adsfasdf123asdfasd234fqewrqew3434rqwerw54qerqwerqwer21321';
      console.log(str.match(/\d+/g));
      
    3. split

      var str = 'zhangsan:12:male;lisi:13:female';
      var arr = str.split(';');
      for (var i = 0; i < arr.length; i++) {
         var item = arr[i].split(':');
         console.log(item[0]);
         console.log(item[1]);
         console.log(item[2]);
      }
      
      var str = 'asdfasdfasdf123asdfas4545dfads';
      var arr = str.split(/\d+/g);
      console.log(arr);
      
    4. replace

      var str = 'adsfasdf123asdfasdf21312sfdsadfad';
      str = str.replace(/\d+/g,'***');
      console.log(str);
      
  • 在非全局匹配模式下轻纪,str.match(reg)reg.exec(str)的作用等效油额。

2.12.2 正則的規(guī)則

  • 元字符:

三、面試題

3.1 ==和===相關(guān)的比較問題

[] ==![]        //true 
[1] == [1]      //false 
[1] == ![1]     //false

比較規(guī)則:

  1. 對象之間的比較是內(nèi)存地址的比較
  2. 單個空對象轉(zhuǎn)成布爾值是true
  3. 空數(shù)組與布爾值的比較會轉(zhuǎn)換成數(shù)值的比較(空數(shù)組會轉(zhuǎn)化成0)
  4. 轉(zhuǎn)成false的情況:false null '' undefined 0 NaN

3.2 in使用中的問題

3.2.1 變量聲明時的問題

console.log('a' in window); //true
if('a' in window){
    var a = 123; 
    console.log(a);
}

console.log('a' in window); //false
if('a' in window){
    a = 123; 
    console.log(a);
}
  • 不使用var不會預解析刻帚,但是也會向window中添加屬性潦嘶。

3.2.2 window中的undefined

console.log(a in window); //true
if(a in window){
    var a = 123; 
    console.log(a);
}
  • 不加引號,a是undefined我擂,window中本身就有一個屬性undefined衬以,并且undefined的值也是undefined缓艳。

3.3 以下代碼的輸出結(jié)果是什么校摩?

var a = {n:1};
var b = a;
a.x = a = {n:2};    //運算符的優(yōu)先級 .的優(yōu)先級最高  賦值操作是從右向左運算的
console.log(a.x);   //undefined
console.log(b.x);   //{n:2}

考點:

  1. 基本類型和引用類型
  2. 引用類型變量和對象屬性(在內(nèi)存實際上就是內(nèi)存地址)
  3. 運算符的優(yōu)先級.的優(yōu)先級最高 ,賦值操作是從右向左運算的

3.4 下列代碼輸出結(jié)果是什么阶淘?

var a = {name:'zhangsan'}; 
var b = {age : 26}; 
var arr = []; 
arr[a] = 123; 
arr[b] = 456; 
console.log(arr);//Array[0] -->[object Object]:456

數(shù)組也是對象

對象屬性的訪問方式

Object的toString方法作用:把構(gòu)造函數(shù)轉(zhuǎn)成這種形式的字符串:[object Object]

3.5 跨域解決方案有哪些衙吩?

  • jsonp
  • cors
  • 反向代理
  • flash插件

3.6 DNS解析過程是什么?

  • DNS Domain Name System : 負責域名和IP地址的映射關(guān)系
  • 域名解析的規(guī)則:先去本機的hosts文件中查找IP溪窒,如果沒有找到坤塞,就去公網(wǎng)的DNS服務(wù)器查找,如果還沒有找到澈蚌,那就無法上網(wǎng)摹芙;如果在hosts文件中找到了,那么就返回ip,就不再去公網(wǎng)查找了

3.7 前端有多少種方式可以發(fā)送請求宛瞄?

1)瀏覽器地址直接輸入url
2)表單的action屬性
3)a標簽href屬性
4)img的src屬性
5)script的src屬性
6)link標簽的href屬性
7)iframe的src屬性
8)Ajax發(fā)送請求
9)postMessage h5新的API
10)flash插件也可以
11)location.href

url的規(guī)范格式
scheme://host:port/path?query#fragment
echeme 表示協(xié)議 http https ftp file ssh
host 表示域名或者IP地址
port 端口 用來確定計算機上的具體某個網(wǎng)絡(luò)應用程序
path 域名之后浮禾,?之前的內(nèi)容 /abc/qqq/rrr
query 查詢字符串份汗,作用是向服務(wù)器傳遞數(shù)據(jù)盈电,格式:鍵=值&鍵=值
fragment hash 錨點 定位頁面的某一部分

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者

  • 序言:七十年代末,一起剝皮案震驚了整個濱河市杯活,隨后出現(xiàn)的幾起案子匆帚,更是在濱河造成了極大的恐慌,老刑警劉巖旁钧,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件吸重,死亡現(xiàn)場離奇詭異,居然都是意外死亡歪今,警方通過查閱死者的電腦和手機嚎幸,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來彤委,“玉大人鞭铆,你說我怎么就攤上這事。” “怎么了车遂?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵封断,是天一觀的道長。 經(jīng)常有香客問我舶担,道長坡疼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任衣陶,我火速辦了婚禮柄瑰,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘剪况。我一直安慰自己教沾,他們只是感情好,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布译断。 她就那樣靜靜地躺著授翻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪孙咪。 梳的紋絲不亂的頭發(fā)上堪唐,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天,我揣著相機與錄音翎蹈,去河邊找鬼淮菠。 笑死,一個胖子當著我的面吹牛荤堪,可吹牛的內(nèi)容都是我干的合陵。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼逞力,長吁一口氣:“原來是場噩夢啊……” “哼曙寡!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寇荧,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤举庶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后揩抡,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體户侥,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年峦嗤,在試婚紗的時候發(fā)現(xiàn)自己被綠了蕊唐。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡烁设,死狀恐怖替梨,靈堂內(nèi)的尸體忽然破棺而出钓试,到底是詐尸還是另有隱情,我是刑警寧澤副瀑,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布弓熏,位于F島的核電站,受9級特大地震影響糠睡,放射性物質(zhì)發(fā)生泄漏挽鞠。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一狈孔、第九天 我趴在偏房一處隱蔽的房頂上張望信认。 院中可真熱鬧,春花似錦均抽、人聲如沸嫁赏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽橄教。三九已至,卻和暖如春喘漏,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背华烟。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工翩迈, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人盔夜。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓负饲,卻偏偏與公主長得像,于是被迫代替她去往敵國和親喂链。 傳聞我的和親對象是個殘疾皇子返十,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355

推薦閱讀更多精彩內(nèi)容