国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

JavaScript中的那些坑

ivyzhang / 1284人閱讀

摘要:序列化為字符串之后它的各個(gè)屬性已經(jīng)被解除了引用,重新相當(dāng)于創(chuàng)建了一個(gè)新的對(duì)象。類似于的,的命令行終端。基本思路函數(shù)的使用以及協(xié)議。

多行注釋的陷阱

由于正則表達(dá)式字面量的存在,多行注釋可能會(huì)產(chǎn)生陷阱,例如以下程序?qū)伋鲥e(cuò)誤:

/*
var a = /h*/.test("hello");
*/

正則結(jié)束前的那個(gè)星號(hào)將被解析為注釋結(jié)束符,從而.被認(rèn)為是不合法的.所以盡量避免使用多行注釋

整型

js采用IEEE754標(biāo)準(zhǔn)表示數(shù)字,整型也是按照64位浮點(diǎn)數(shù)進(jìn)行處理的,也就意味著2===2.0,這種設(shè)計(jì)的一個(gè)優(yōu)點(diǎn)是避免了整型的溢出.JavaScript中精確的整型的范圍是(-2^53,2^53),ES6中的2個(gè)常量:Number.MAX_SAFE_INTEGERNumber.MIN_SAFE_INTEGER

Math.pow(2,53) +1 === Math.pow(2,53) // true
遍歷對(duì)象的屬性

for-in循環(huán)可以枚舉對(duì)象以及它原型上的屬性,我們可以通過hasOwnProperty()進(jìn)行過濾,例如:

for(var key in obj){
  // 以下的過濾還可以使用typeof obj[key] !== "function"
  if(obj.hasOwnProperty(key)){
    console.log(key,"=>",obj[key]);
  }
}
函數(shù)

在js中函數(shù)就是對(duì)象,對(duì)象是"名/值"對(duì)的集合并擁有一個(gè)連接到原型對(duì)象的隱藏連接.對(duì)象字面量產(chǎn)生的對(duì)象連接到Object.prototype.函數(shù)對(duì)象連接到Function.prototype(該原型對(duì)象本身連接到Object.prototype).每個(gè)函數(shù)在創(chuàng)建時(shí)附有2個(gè)附加的隱藏屬性:函數(shù)的上下文和實(shí)現(xiàn)函數(shù)行為的代碼.

因?yàn)楹瘮?shù)是對(duì)象,所以它們可以像其他任何值一樣被使用.函數(shù)可以存放在變量,對(duì)象和數(shù)組中,函數(shù)可以被當(dāng)做參數(shù)傳遞給其他函數(shù),函數(shù)也可以再返回函數(shù),函數(shù)也可以擁有方法.函數(shù)與普通對(duì)象的不同之處僅僅在于它可以被調(diào)用.

帶有緩存的函數(shù)

函數(shù)可以使用對(duì)象緩存之前的計(jì)算結(jié)果從而減少不必要的計(jì)算,這是程序優(yōu)化的一種方式,例如,對(duì)于斐波那契數(shù)列我們可以這樣優(yōu)化:

var fibonacci = function(){
  var memo = [0,1]
  var fib = function(n){
    var result = memo[n]
    if(typeof result !== "number"){
      result = fib(n - 1) + fib(n - 2)
      memo[n] = result
    }
    return result
  }
  return fib
}()

我們可以將這種形式推廣到一般函數(shù):

var memoizer = function(memo,fundamental){
  var shell = function(n){
    var result = memo[n]
    if(typeof result !== "number"){
      result = fundamental(shell,n)
      memo[n] = result
    }
    return result
  }
  return shell
}

var fib = memoizer([0,1],function(shell,n){
  return shell(n-1) + shell(n-2)
})

var fac = memoizer([1,1],function(shell,n){
  return n * shell(n-1)
})
繼承

當(dāng)一個(gè)函數(shù)對(duì)象被創(chuàng)建時(shí),Function構(gòu)造器產(chǎn)生的函數(shù)對(duì)象會(huì)運(yùn)行類似這樣的一些代碼:

this.prototype = {constructor:this};

新函數(shù)對(duì)象被賦予一個(gè)prototype屬性,其值是包含在一個(gè)constructor屬性并且屬性值為該函數(shù)的新對(duì)象.該prototype對(duì)象是存放繼承特征的地方.因?yàn)閖avascript語言沒有提供一種方法去確定哪個(gè)函數(shù)是打算用來做構(gòu)造器的,所以每個(gè)函數(shù)都會(huì)得到一個(gè)prototype對(duì)象(非常重要).

通過偽類的方式實(shí)現(xiàn)繼承

本質(zhì)上來說就是子類的原型等于父類的實(shí)例,實(shí)例如下:

var SuperType = function(){
  this.superValue = "supper value"
}
var SubType = function(){
  this.subValue = "sub value"
}
SubType.prototype = new SuperType()
var sub = new SubType()
console.log(sub.subValue) // subvalue
console.log(sub.superValue) // supervalue
數(shù)組

javascript中并沒有真正的數(shù)組,數(shù)組本質(zhì)上也是對(duì)象

請(qǐng)看下面的例子:

var arr = [1,2,3,4,5,6]
console.log(arr.length) // 6
arr.abc = false         // 給數(shù)組增加屬性
console.log(arr)        // [1, 2, 3, 4, 5, 6, abc: false]
console.log(arr.length) // 6

由運(yùn)行的結(jié)果可以看出給數(shù)組添加了一個(gè)abc屬性,盡管字面上的長度有所增加,但是數(shù)組的實(shí)際長度并沒有改變!

typeof [] // "object"

所以為了區(qū)分?jǐn)?shù)組和對(duì)象我們應(yīng)該可以采用以下的函數(shù):

let isArray = value => !!value && typeof value === "object" && value.constructor === Array
正則表達(dá)式 分組

觀察以下匹配url的正則表達(dá)式:

"use strict"

let parse_url = /^(?:([A-Za-z]+):)?(/{0,3})([0-9.-A-Za-z]+)(?::(d+))?(?:/([^?#]*))?(?:?([^#]*))?(?:#(.*))?$/

let url = "http://www.ora.com:80/goods?q=1#fragment"

let result = parse_url.exec(url)

let names = ["url","schema","slash","host","port","path","query","hash"]

for(let i = 0;i < names.length;i++){
  console.log(names[i] + ":",result[i])
}

(?:([A-Za-z]+):)?這個(gè)因子匹配一個(gè)協(xié)議名,但僅當(dāng)它之后跟隨一個(gè)冒號(hào)(:)的時(shí)候才匹配(?:...)表示一個(gè)非捕獲型分組(noncapturing group),通常用非捕獲分組來代替少量不優(yōu)美的捕獲型分組是很好的方法,因?yàn)椴东@會(huì)有性能上的缺失.后綴?表示這個(gè)分組是可選的.(...)表示一個(gè)捕獲型分組(capturing group).一個(gè)捕獲型分組將復(fù)制它所匹配的文本,并將其放入到result數(shù)組中.每個(gè)捕獲型分組都將被指定一個(gè)編號(hào),第一個(gè)捕獲分組的編號(hào)是1,所以該分組所匹配的文本拷貝將出現(xiàn)在result[1]中;下一個(gè)因子(/{0,3})是捕獲分組2.

常用正則

匹配數(shù)字

pattern_number = /^-?d+(?:.d*)?(?:e[+-]?d+)?$/i
正則表達(dá)式轉(zhuǎn)義

1指向分組1所捕獲到的文本的一個(gè)引用,所以它能夠再次匹配,例如我們用下面的正則表達(dá)式來搜索文本中重復(fù)的單詞:

var doubled_words = /[A-Za-zu00c0-u1fffu2800-ufffd-]+s+1/gi
正則表達(dá)式分組 捕獲型

一個(gè)被包圍在圓括號(hào)中的正則表達(dá)式選擇.任何匹配這個(gè)分組的字符將被捕獲.每個(gè)捕獲分組都被指定了一個(gè)數(shù)字,第一個(gè)捕獲(的是分組1,第二個(gè)捕獲(的是分組2

非捕獲型

有一個(gè)(?:前綴,僅做簡單匹配,并不會(huì)捕獲所匹配文本,會(huì)有微弱的性能優(yōu)勢(shì),不會(huì)干擾捕獲型分組的編號(hào).

關(guān)于語言本身的一些探討 位運(yùn)算

由于javascript中所有數(shù)字都是浮點(diǎn)型,所以使用位運(yùn)算會(huì)降低程序性能,因?yàn)樾枰獙?shù)字轉(zhuǎn)化為整型后執(zhí)行運(yùn)算然后轉(zhuǎn)化回去.

巧妙使用位運(yùn)算可以創(chuàng)造很多的奇淫技巧。例如以下的轉(zhuǎn)化為整數(shù)的代碼:

let parseInt = num => num | 0
// 還可以這樣
let parseInt = num => num >>> 0
// 甚至,我們可以這樣
let parseInt = num => ~~num

以上的parseInt實(shí)現(xiàn)可以傳入任意的數(shù)據(jù)類型,如果數(shù)據(jù)類型不匹配將會(huì)被轉(zhuǎn)化為0,避免了原生的parseInt中的NaN的問題,但是局限在于只能處理32位的整數(shù)

JSON.stringifyJSON.parse的妙用

我們可能見到這樣的函數(shù):

let f = uid => {
  let user = global.__user[uid]
  let game = global.__game[uid]

  let userInfo = JSON.parse(JSON.stringify(user))
  let gameInfo = JSON.parse(JSON.stringify(game))
  
  let ret = {
    user: userInfo,
    game: gameInfo
  }
  
  return ret
}

思考上述的過程是不是存在重復(fù)?為什么要將一個(gè)對(duì)象變成字符串,然后再將字符串解析為對(duì)象?我們明明可以直接使用那個(gè)對(duì)象?其實(shí)let objs = JSON.parse(JSON.stringify(obj))執(zhí)行的是對(duì)象的深度克隆操作。序列化為字符串之后它的各個(gè)屬性已經(jīng)被解除了引用,重新JSON.parse相當(dāng)于創(chuàng)建了一個(gè)新的對(duì)象。當(dāng)然對(duì)象的克隆本身有很多方法,例如:lodash的_.clone

數(shù)組復(fù)制

數(shù)組復(fù)制其實(shí)有很多方法:

var arr2 = arr1.concat();
var arr2 = arr1.filter(n => true);
var arr2 = arr1.map(n => n);
js實(shí)現(xiàn)node的REPL模式

一個(gè)簡易的JavaScript解釋器。類似于ruby的irb,Scala的命令行終端。

基本思路:eval函數(shù)的使用以及UDP協(xié)議。實(shí)現(xiàn)如下:

server.js

"use strict"

const dgram = require("dgram")

let udp = dgram.createSocket("udp4")

const PORT = 8888
const ADDRESS = "127.0.0.1"

udp
    .on("message",(data,rinfo) => {
        let cmd = data.toString().trim()
        console.log(`get cmd [${cmd}] from ${rinfo.address} : ${rinfo.port}`)
        let evalRes
        try {
            evalRes = new Buffer("=> " + JSON.stringify(eval(cmd)) + "
javascript>")
            
        } catch (ex) {
            console.trace("udp 2>", ex.stack)
            evalRes = new Buffer(ex.stack)
        }
        udp.send(evalRes,0,evalRes.length,rinfo.port,rinfo.address)
    })
    .on("error",err => {
        console.trace(err.stack)
        udp.close()
    })
    .on("close",() => {
        process.exit()
    })
    .on("listening",() => {
        let addr = udp.address()
        console.log(`command server listen on ${addr.address} : ${addr.port}`)
    })
    .bind(PORT,ADDRESS)

client.js

"use strict"

const dgram = require("dgram")
let udp = dgram.createSocket("udp4")

const stdin = process.stdin
const PORT = 8888
const ADDRESS = "127.0.0.1"

stdin.resume()
stdin.setEncoding("utf-8")

console.log("javascript>")

udp.on("message",(msg,rinfo) => {
    try {
        msg = JSON.parse(msg.toString())
    } catch (e) {
        msg = msg.toString()
    }
    console.log(msg)
})

stdin.on("data",chunk => {
    let msg = new Buffer(chunk)
    udp.send(msg,0,msg.length,PORT,ADDRESS)
})

生成隨機(jī)字母數(shù)字字符串
function generateRandomAlphaNum(len) {
    var rdmString = "";
    for( ; rdmString.length < len; rdmString  += Math.random().toString(36).substr(2));
    return  rdmString.substr(0, len);
}

toString(36)表示10個(gè)阿拉伯?dāng)?shù)字和26個(gè)小寫英文字母

隨機(jī)背景色
"#"+(0x1000000+(Math.random())*0xffffff).toString(16).substr(1,6)
在js中如何優(yōu)雅實(shí)現(xiàn)sleep

promise

function sleep(delay){
  return function(){
    return new Promise(function(resolve, reject){
      setTimeout(resolve, delay);
    });
  }
}

var promise = new Promise(function(resolve){
  console.log("do something");
  resolve();
}).then(sleep(2000)).then(function(){
  console.log("after sleep 2000");
});

generator

function sleep(ms) {
  return function (cb) {
    setTimeout(cb, ms);
  };
}

co(function *() {
  var now = Date.now();
  yield sleep(2000);
  expect(Date.now() - now).to.not.be.below(2000);
})();

參見知乎

underscore.js中的_.after方法

該方法可以根據(jù)傳入的times參數(shù)的不同生成需要調(diào)用多次才執(zhí)行的實(shí)際函數(shù)的函數(shù),這是偏函數(shù)的典型應(yīng)用

var _ = require("underscore")
var count = 5;
var fiveCountCallback = _.after(count,function(){
    console.log("after 5 count and execute this function")
})
var timer = 0
setInterval(function(){
    console.log(timer++)
    fiveCountCallback() // 每1s執(zhí)行一次該函數(shù),但是真正執(zhí)行該函數(shù)卻是在55后
}, 1000)
console.log("this will print first")

其內(nèi)部實(shí)現(xiàn)如下:

_.after = function(times, func) {
  return function() {
    if (--times < 1) {
      return func.apply(this, arguments);
    }
  };
};
對(duì)象的鍵

對(duì)象的鍵如果是數(shù)字,則按照數(shù)字進(jìn)行升序排序。

obj = {"100":"a","99":"b"} // { "99": "b", "100": "a" }
"100" > "99" // false

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/80138.html

相關(guān)文章

  • JavaScript四舍五入的那些

    摘要:進(jìn)制之謎眾所周知,計(jì)算機(jī)在設(shè)計(jì)之初,出于各方面角度考慮,最終采用二進(jìn)制的格式來存儲(chǔ)數(shù)據(jù)。同樣的情況,也會(huì)出現(xiàn)在十進(jìn)制和二進(jìn)制的轉(zhuǎn)換中。當(dāng)我們?cè)谟?jì)算機(jī)中,聲明一個(gè)變量為,其實(shí)該數(shù)字作為二進(jìn)制保存在計(jì)算機(jī)中,并不真的是。 前言 經(jīng)常使用JavaScript用來處理數(shù)字的程序員都知道,JavaScript的Number.toFixed,這一函數(shù),在格式化數(shù)字時(shí),會(huì)自動(dòng)進(jìn)行四舍五入,例如: 1...

    zollero 評(píng)論0 收藏0
  • JavaScript中,關(guān)于變量和聲明的一些

    摘要:主要講述了中關(guān)于變量聲明和代碼編寫時(shí)你可能沒它留意的一些坑。但是換行符并不會(huì)被忽略,換行符起到了分號(hào)的功能。需要注意的是,大小寫敏感,和是兩個(gè)不同的變量。保留字中有一批稱為保留字的家伙是不能用做變量的,用了在一些瀏覽器中很可能會(huì)報(bào)錯(cuò)。 今天翻譯的這篇文章依舊比較基礎(chǔ),是這個(gè)系列文章的第三篇。主要講述了JavaScript中關(guān)于變量聲明和代碼編寫時(shí)你可能沒它留意的一些坑。 那些熟悉PHP...

    lowett 評(píng)論0 收藏0
  • 前端入指南

    摘要:作為自學(xué)兩年的初級(jí)前端,希望對(duì)那些想入門前端開發(fā)的人分享一些觀點(diǎn)。尤其是這幾年前端領(lǐng)域飛速的發(fā)展,新東西層出不窮。或者關(guān)注下我的微信公眾號(hào)前端獲取每天分享前端入門知識(shí)。為什么選擇前端 做一件事之前最好問問自己為什么要做,然后再去思考該怎么做。如果只是看到別人做了,并且有很不錯(cuò)的收入,然后自己就決定做了,很可能中途放棄浪費(fèi)掉很多時(shí)間。起碼問自己一個(gè)問題:我是否真的熱愛這個(gè)領(lǐng)域,并且很樂意在這個(gè)...

    junnplus 評(píng)論0 收藏0
  • JavaScript操作DOM的那些

    摘要:在操作中存在著許多跨瀏覽器方面的坑,本文花了我將近一周的時(shí)間整理,我將根據(jù)實(shí)例整理那些大大小小的坑。在火狐中,與等效的是。對(duì)象的屬性則表示文檔的根節(jié)點(diǎn)。不區(qū)分和在下使用和時(shí)會(huì)同時(shí)返回或與給定值相同的元素。 js在操作DOM中存在著許多跨瀏覽器方面的坑,本文花了我將近一周的時(shí)間整理,我將根據(jù)實(shí)例整理那些大大小小的坑。 DOM的工作模式是:先加載文檔的靜態(tài)內(nèi)容、再以動(dòng)態(tài)方式對(duì)它們進(jìn)行刷新,...

    RiverLi 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<