task0002(一)- JavaScript數據類型及語言基礎

轉載自個人我的博客javascript

歡迎你們批評指正php

1. 第一個頁面交互

  • 這裏最須要學習的老師的代碼中,每一部分功能都由函數控制,沒有建立一個所有變量。且最後有一個函數來控制執行代碼。這個更多的是思想上的學習吧!html

  • 在chrome上相加時,直接兩個數拼接到一塊兒了,而不是數值相加。由於輸入的值,在獲取時,默認是字符串類型的。java

  • 在IE8下提示對象不支持「addEventListener」屬性或方法。緣由是IE8不支持標準的DOM事件綁定函數,它使用attachEventgit

1.1 瞭解JavaScript是什麼

JavaScript,一種直譯式腳本語言,是一種動態類型、基於原型的語言,內置支持類。它的解釋器被稱爲JavaScript引擎,爲瀏覽器的一部分,普遍用於客戶端的腳本語言,最先是在HTML網頁上使用,用來給HTML網頁增長動態功能。然而如今JavaScript也可被用於網絡服務器,如Node.js。github

上面是維基百科上的解釋。不過讓JavaScript流行起來的緣由應該是JavaScript 是目前全部主流瀏覽器上惟一支持的腳本語言。下面是MDN對其核心功能的解釋web

核心的 JavaScript 中包含有一組核心的對象,包括 Array,Date 和 Math,以及一組核心的語言要素,包括操做符,控制結構和語句。出於多種目的,能夠經過爲其增補附加的對象,對核心 JavaScript 加以擴展;例如:正則表達式

  • 客戶端: JavaScript 提供了用於控制瀏覽器(Navigator 或者其它瀏覽器)以及其中的文檔對象模型(DOM)的對象,從而擴展了核心 JavaScript。例如,客戶端擴展容許應用程序在 HTML 的表單中加入元素,以便響應用戶事件,好比鼠標點擊,表單輸入和頁面導航。chrome

  • 服務器端: JavaScript 提供了服務於在服務器上運行 JavaScript 的對象,從而擴展了核心 JavaScript。例如,服務器端擴展能夠容許應用程序訪問關係型數據庫,在應用程序的不一樣調用間提供信息的連續性,甚至於處理服務器之上的文件。數據庫

1.2 如何在HTML頁面加載JavaScript代碼

能夠有三種方法加載在HTML頁面中引入JavaScript代碼:

  1. 內聯式: 在HTML標籤的style屬性中定義樣式,在onclick這樣的屬性中定義Javascript代碼;

  2. 嵌入式: 在頁面中使用<script>標籤訂義Javascript代碼;

  3. 引用外部文件: 在<script>標籤中定義src屬性引入Javascript文件.

注意:在<head>或者<body>中均可以建立<script>標籤來建立或者引入JavaScript代碼。

  • 搜索一下,爲何咱們讓你把<script>放在</body>前。

    1. 瀏覽器在解釋HTML頁面時,是按照前後順序的,所在放在前面的JS代碼就會先被執行。正是由於這種特性,因此放在<head>中的<script>代碼會阻塞頁面的渲染。

    2. 其實有些JS代碼能夠放在<head></head >之間,好比IE9如下瀏覽器兼容HTML5標籤的js代碼,這是一個底層的兼容腳本,不涉及任何頁面邏輯。那麼它應該放在<head></head >間。

    3. 新版瀏覽器<script>標籤可使用defer屬性來延遲加載。

最簡單的不就是把能放在body中的代碼放進去嗎?擴展閱讀中有詳細介紹。

1.3 擴展閱讀:

2. JavaScript數據類型及語言基礎

  • 建立一個JavaScript文件,好比util.js

  • 實踐判斷各類數據類型的方法,並在util.js中實現如下方法:

2.1 判斷各類數據類型的方法

這裏比較簡單,能夠參考個人另外一篇博客JavaScript類型識別.

// 判斷arr是否爲一個數組,返回一個bool值
function isArray(arr) {
    return typeof (arr) === "object" && Object.prototype.toString.call(arr) === "[object Array]";
}

// 判斷fn是否爲一個函數,返回一個bool值
function isFunction(fn) {
    return typeof (fn) === "function";
}

在ECMAScript5中,判斷數組類型能夠直接使用Array.isArray()

Array.isArray([]); //true
Array.isArray(function(){}); //false

2.2 值類型和引用類型的區別.各類對象的讀取、遍歷方式

  • 瞭解值類型和引用類型的區別,瞭解各類對象的讀取、遍歷方式,並在util.js中實現如下方法:

2.2.1 深度克隆

// 使用遞歸來實現一個深度克隆,能夠複製一個目標對象,返回一個完整拷貝
// 被複制的對象類型會被限制爲數字、字符串、布爾、日期、數組、Object對象。不會包含函數、正則對象等
function cloneObject(src) {
    // your implement
}

// 測試用例:
var srcObj = {
    a: 1,
    b: {
        b1: ["hello", "hi"],
        b2: "JavaScript"
    }
};
var abObj = srcObj;
var tarObj = cloneObject(srcObj);

srcObj.a = 2;
srcObj.b.b1[0] = "Hello";

console.log(abObj.a);
console.log(abObj.b.b1[0]);

console.log(tarObj.a);      // 1
console.log(tarObj.b.b1[0]);    // "hello"

思路以下

  1. 題目考的主要是有些對象的使用=直接賦值,並非真正的複製,而是將一個新的變量指向了當前對象,共享同一個地址。在修改原對象時,新對象也會跟着改變。

  2. 通過測試,數字、字符串、布爾、日期、能夠直接賦值,修改不會產生影響。因此就思考了在使用typeof值爲對象或者是原始類型時的狀況。且對象類型爲Date對象時,也使用直接賦值的方式。

  3. 再考慮對象類型爲Array或者Object的狀況。對於結果聲明其類型。

  4. 接着往下走,在遍歷對象時,只考慮其自身的屬性,而不考慮繼承來屬性。若其自身值仍是對象,那麼 就遞歸調用,進一步解析、賦值,不然直接賦值。

實現:

function cloneObject(src) {
    var result ;//返回的複製後的結果。
    if (typeof(src)==="object"){
        //對象爲日期對象時也直接賦值。
        if(Object.prototype.toString.call(src)==="[object Date]"){
            result = src;
        }else{
            //判斷對象的類型是Array仍是Object,結果類型更改。
            result = (Object.prototype.toString.call(src)==="[object Array]")? [] : {};
            for (var i in src){
                if (src.hasOwnProperty(i)) { //排除繼承屬性
                    if (typeof src[i] === "object") {
                        result[i] = cloneObject(src[i]); //遞歸賦值
                    } else {
                        result[i] = src[i]; //直接賦值
                    }
                }
            }
        }
    }else{
        //對於原始類型直接賦值。
        result = src;
    }
    return result;
}

2.3數組、字符串、數字等相關方法

  • 學習數組、字符串、數字等相關方法,在util.js中實現如下函數

2.3.1 數組去重操做

// 對數組進行去重操做,只考慮數組中元素爲數字或字符串,返回一個去重後的數組
function uniqArray(arr) {
    // your implement
}
// 使用示例
var a = [1, 3, 5, 7, 5, 3];
var b = uniqArray(a);
console.log(b); // [1, 3, 5, 7]

思路以下:

  1. 新建一下新數組

  2. 循環原數組

  3. 判斷新數組內元素,原數組是否含有.含有則跳過

    • 這裏使用了數組的indexOf方法,找到某個元素在數組中的索引。簡化了查找過程,若使用最簡單的遍歷尋找的話須要嵌套循環,是這樣的,先在循環中取原數組的值,再循環在新數組中查找,如有相等的狀況就不添加。(這是個人第一想法,顯然比如今複雜不少).

    • 參看來自MDN的Array對象.裏面介紹了一下數組的方法.

  4. 返回新數組.

實現:

function uniqArray(arr) {
    // your implement
    var result = []; //建立一個新數組。
    for (var i = 0, l = arr.length; i < l; i++) {
        if (result.indexOf(arr[i]) === -1) { //查找是否已經含有該元素
            result.push(arr[i]); //添加到新數組
        }
    }
    return result; //返回新數組

}

2.3.2 實現trim函數,去除字符串首尾空白

  • 實現一個簡單的trim函數,用於去除一個字符串,頭部和尾部的空白字符

//1.字符串查找
// 假定空白字符只有半角空格、Tab
// 練習經過循環,以及字符串的一些基本方法,分別掃描字符串str頭部和尾部是否有連續的空白字符,而且刪掉他們,最後返回一個完成去除的字符串
function simpleTrim(str) {
    // your implement
}
//2.正則
// 不少同窗確定對於上面的代碼看不下去,接下來,咱們真正實現一個trim
// 對字符串頭尾進行空格字符的去除、包括全角半角空格、Tab等,返回一個字符串
// 嘗試使用一行簡潔的正則表達式完成該題目
function trim(str) {
    // your implement
}
// 使用示例
var str = '   hi!  ';
str = trim(str);
console.log(str); // 'hi!'

實現以下:

//1.字符串查找
//這裏就是利用兩個循環,找到頭尾第一個不是空格且不是tab符的元素。記錄它們的索引,以後截取字符串。
function simpleTrim(str) {
    // your implement
    var result = "";
    for (var i = 0, il = str.length; i < il; i++) { //從頭查找
        if (str[i] != " " && str[i] != "\t") {
            break; //查找到第一個不爲空格及tab符的元素
        }

    }
    for (var j = str.length - 1; j >= 0; j--) { //從尾查找
        if (str[j] != " " && str[j] != "\t") {
            break;
        }

    }
    result = str.slice(i, j + 1); //截取須要的字符串。
    return result;
}
//2.正則
function trim(str) {
    // your implement
    var result = "";
    result = str.replace(/^\s+|\s+$/g, ""); //使用正則進行字符串替換
    return result;
}

2.3.3 遍歷數組,對每個元素執行fn函數

// 實現一個遍歷數組的方法,針對數組中每個元素執行fn函數,並將數組索引和元素做爲參數傳遞
function each(arr, fn) {
    // your implement
}

// 其中fn函數能夠接受兩個參數:item和index

// 使用示例
var arr = ['java', 'c', 'php', 'html'];
function output(item) {
    console.log(item)
}
each(arr, output);  // java, c, php, html

// 使用示例
var arr = ['java', 'c', 'php', 'html'];
function output(item, index) {
    console.log(index + ': ' + item)
}
each(arr, output);  // 0:java, 1:c, 2:php, 3:html

思路以下:

  1. 這裏的實現有點相似ECMA5中數組的forEach()方法

  2. 由示例可知:item爲必須參數,index爲可選參數.

  3. 且item爲數組項,index爲數組索引.

  4. 這樣就簡單了,循環傳參.

實現:

function each(arr, fn) {
    // your implement
    for (var i = 0, l = arr.length; i < l; i++) {//遍歷傳參
        fn(arr[i], i);
    }
}

2.3.4 獲取對象裏第一層元素的數量,返回整數

// 獲取一個對象裏面第一層元素的數量,返回一個整數
function getObjectLength(obj) {}

// 使用示例
var obj = {
    a: 1,
    b: 2,
    c: {
        c1: 3,
        c2: 4
    }
};
console.log(getObjectLength(obj)); // 3

實現:

//使用for in遍歷時,直接獲取到的就是第一層的結果
//排除繼承來的屬性,使用外部變量保存循環次數
function getObjectLength(obj) {
    var count = 0;
    for (var i in obj) {
        if (obj.hasOwnProperty(i)) {
            count++;
        }
    }
    return count;
}

正則表達式

// 判斷是否爲郵箱地址
function isEmail(emailStr) {
    // your implement
}

// 判斷是否爲手機號
function isMobilePhone(phone) {
    // your implement
}

實現思路

這裏參考我對於正則表達式入門的兩篇博客

  • 正則表達式-基礎實戰篇

  • 手機號碼的匹配

    1. 這裏匹配的狀況是最簡單的狀況,並無特別完美,好比限制開頭第二位數字的範圍:188,158經過,而123,191,不經過等等。

    2. 可利用多選分支,例如:/^1[3|5][0-9]{9}$|^18\d{9}$/。不過如今虛擬運營商的加入,號碼段變多了,因此直接用最簡單的方法,也沒事。

  • 郵箱的匹配

    1. 在@前能出現哪些東西?這裏使用(\w+\.)*來匹配出現.的狀況,表示出現0次或屢次由於.後不能緊跟@,因此後面緊跟\w+匹配普通的字母數字狀況。

    2. @後出現的郵箱後綴並不固定因此使用\w+來匹配。

    3. 最後考慮域名結尾的級聯狀況因此用(\.\w+)+

實現以下:

// 判斷是否爲郵箱地址
function isEmail(emailStr) {
    // your implement
    var reg = /^(\w+\.)*\w+@\w+(\.\w+)+$/;
    return reg.test(emailStr);
}

// 判斷是否爲手機號
function isMobilePhone(phone) {
    // your implement
    var reg = /^1\d{10}$/;
    return reg.test(phone);
}

2.4 參考資料

相關文章
相關標籤/搜索