JavaScript中心概念及实践

1.JavaScript中的数据范例

在Javascript中,包含6种数据范例:字符串(string)、数值(number)、布尔值(boolean)、undefined、null以及对象(object)。PS:第6种应当是object照样symbo(ES6)?

2.JavaScript中的对象

此处的对象包含:对象(属性的鸠合,即键值的散列表)、数组(有序的列表)、函数(包含可实行的代码)

3.相称与同等运算符

相称运算符:假如操纵数具有雷同的范例,则推断其同等性,假如两个操纵数的值相称,则返回true,不然返回false。
假如操纵数的范例差别,则依据如许的状况来推断:

  • null和undefined相称;
  • 个中一个是数字,另一个是字符串,则将字符串转换为数字,再做比较;
  • 个中一个是true,先转换为1(false转为0)再做比较;
  • 假如一个值是对象,另一个是数字/字符串,则将对象转换为原始值(经由历程toString()或许valueOf());
  • 其他状况,直接返回false。

<br/>

同等运算符(===):假如操纵数的范例差别,则不举行值的推断,直接返回false。
假如操纵数的范例雷同,分以下状况来推断:

  • 都是数字的状况,假如值雷同,则二者同等(有一个破例,就是NaN,NaN与其本身也不相称),不然差别等;
  • 都是字符串的状况,与其他顺序设计言语一样,假如串的值不相称,则差别等;
  • 都是布尔值,且值均为true/false,则同等;
  • 假如两个操纵数援用同一个对象(数组,函数),则二者完整同等;

假如两个操纵数均为null/undefined,则同等。

4.原型对象及原型链

javascript本身是基于原型的,每一个对象都有一个prototype的属性,这个prototype本身也是一个对象,因而它本身也能够有本身的原型,如许就构成了一个链组织。

接见一个属性的时刻,解析器须要从下向上的遍历这个链组织,直到碰到该属性,则返回属性对应的值,或许碰到原型为null的对象(javascript的基对象Object的组织器的默许prototype有一个null原型),假如此对象仍没有该属性,则返回undefined。

5.数组对象的要领

要领形貌
concat()衔接两个或更多的数组,并返回效果数组
join()把数组的一切元素放入一个字符串。元素经由历程指定的分开符举行分开
pop()删除并返回数组的末了一个元素
push()向数组的末端增加一个或更多元素,并返回新的长度
reverse()倒置数组中元素的递次
shift()删除并返回数组的第一个元素
slice()从某个已有的数组返回选定的元素
sort()对数组的元素举行排序
splice()删除元素,并向数组增加新元素
unshift()向数组的开首增加一个或更多的元素,并返回新的长度
valueOf()返回数组对象的原始值

6.借助数组对象本身的slice要领删除数组某个数据

jQuery的设计者John Resig供应的要领

Array.prototype.remove = function (from, to) {
    var rest = this.slice((to || from) + 1 || this.length);
    this.length = from < 0 ? this.length + from : from;
    return this.push.apply(this.rest);
};

array.remove(0);//删除第一个元素
array.remove(-1);//删除倒数第一个元素
array.remove(0,2);//删除数组下标为0-2的元素(3个)

7.正则表达式

元字符寄义
^串的最先
$串的完毕
*零到屡次婚配
+一到屡次婚配
?零或一次婚配
b单词边境
字符寄义
字符本身婚配字符本身
r婚配回车
n婚配换行
t制表符
f换页
x#婚配十六进制数
cX婚配掌握字符
标志符寄义
[…]在鸠合中的任一个字符
1不在鸠合中的任一个字符
.除n以外的任一个字符
w一切的单字,包含字母数字及下划线
W不包含一切的单字,w的补集
s一切的空缺字符,包含空格,制表符
S一切的非空缺字符
d一切的数字
D一切的非数字
b退格字符
标记寄义
{n}反复n次
{n,}反复n或更屡次
{n,m}反复最少n次,最多m次
var pid = /^(\d{15}|\d{18})&/;//身份证
var mphone = /\d{11}/;//手机号码
var phone = /\d{3,4}-\d{7,8};//电话号码

8.运用正则表达式

竖立正则表达式:

  • 运用字面量:var regex = /pattern/;
  • 运用RegExp对象:var regex = new RegExp("pattern", switchs);

而正则表达式的平常情势形貌为:var regex = /pattern/[switchs];

这里的开关(switchs)有以下三种:

修饰符形貌
i疏忽大小写开关
g全局搜刮开关
m多行搜刮开关(重定义^与$的意义)

正则表达式对象的要领:

要领名形貌
test()测试串中是不是有符合形式的婚配
exec()对串举行婚配
compile()编译正则表达式

9.String中的正则表达式

除了正则表达式对象及字面量外,String对象中也有多个要领支撑正则表达式操纵。

要领作用
match婚配正则表达式,返回婚配数组
replace替换
split支解
search查找,返回初次发明的位置
var str = "life is very much like a mirror.";
var result = str.match(/is|a/g);//返回["is", "a"]

var str = "<span>Welcome, John</span>";
var result = str.replace(/span/g, "div");//<div>Welcome, John</div>

假如想把Welcome和John两个单词换取递次:
var result = str.replace(/(\w+),\s(\w+)/g, "$2, $1");
//<span>John,Welcome</span>

10.正则表达式中括号的作用

  1. 括号用来将子表达式标记起来,以区分于其他表达式,比方许多的敕令行顺序都供应协助敕令,键入h和键入help的意义是一样的,那末就会有如许的表达式:h(elp)?//字符h以后的elp无足轻重
  2. 括号用来分组,当正则表达式实行完成以后,与之婚配的文本会按划定规矩填入各个分组。
    比方:

    var pattern = /\w{4}(\d{4})(\w{2})/;
    var result = pattern.exec("yunn0871cg");
    console.log("city code = " + result[1] + ", county code = " + result[2]);
    //city code = 0871, county code = cg
    

    正则表达式的exec要领会返回一个数组,数组的第一个元素(下标为0)示意全部串,第一个元素为第一个分组,第二个元素为第二个分组;

  3. 第三种状况,括号用来对援用起辅佐作用,即在同一个表达式中,后边的式子能够援用前边婚配的文本。

11.匿名自实行函数

有的函数只须要实行一次,其内部变量无需保护,比方UI的初始化,那末我们能够运用闭包。比方:

var datamodel = {
    table: [],
    tree: {}
};

(function (dm) {
    for (var i = 0; i < dm.table.rows; i++) {
        var row = dm.table.rows[i];
        for (var j = 0; j < row.cells; i++) {
            drawCell(i, j);
        }
    }
})(datamodel);

我们竖立了一个匿名的函数,并马上实行它,由于外部没法援用它内部的变量,因而在实行完后很快就会被开释,最重要的是这类机制不会污染全局对象。

12.缓存

想象我们有一个处置惩罚历程很耗时的函数对象,每次挪用都邑消费很长时候,那末我们就须要将盘算出来的值存储起来,当挪用这个函数的时刻,起首在缓存中查找,假如找不到,则举行盘算,然后更新缓存并返回值,假如找到了,直接返回查找到的值即可。闭包能够做到这一点,由于它不会开释外部的援用,函数内部的值能够得以保存。

var CachedSearchBox = (function () {
    var cache = {}, count = [];
    return {
        attachSearchBox: function (disd) {
            if (disd in cache) {//假如在缓存中
                return cache[disd];//直接返回
            }
            var fsb = new uikit.webctrl.SearchBox(disd);//竖立
            cache[disd] = fsb;//更新缓存
            if (count.length > 100) {//保证缓存的大小小于100个
                delete cache[count.shift()];//删除最前面谁人缓存
            }
            return fsb;
        },
        clearSearchBox: function (disd) {
            if (disd in cache) {
                cache[disd].clearSelection();
            }
        }
    }
})();

CachedSearchBox.attachSearchBox("input1");

13.闭包完成封装

var person = function () {
    //变量作用域为函数内部,外部没法接见
    var name = "default";
    return {
        getName: function () {
            return name;
        },
        setName: function (newName) {
            name = newName;
        }
    }
}();

person.name;//undefined
person.getName();//default
person.setName("aaa");
person.getName();//aaa

14.闭包中的this

关于this我们之前已做过议论,它示意对挪用对象的援用,而在闭包中,最轻易涌现毛病的处所是误用了this。在js的开辟中,一个罕见的毛病就是将this类比为其他的外部部分变量。

$(function () {
    var con = $("#div#panel");
    this.id = "content";
    con.click(function () {
        alert(this.id);//panel
    })
});

此处的this.id究竟援用着什么呢?许多开辟者能够依据闭包的观点,做出毛病的推断:content,理由是,this.id显现的被赋值为content。然则现实上,这个alert会弹出panel,究其原因,就是此处的this,由于挪用对象的存在,使妥当闭包被挪用时(当这个panel的click发作时),this援用的是con这个jQuery对象。而匿名函数中的this.id=”content”是对匿名函数本身做的操纵。两个this援用的不是同一个对象。假如想要在事宜处置惩罚函数中接见这个值,我们必需做一些转变:

$(function () {
    var con = $("#div#panel");
    this.id = "content";
    var self = this;
    con.click(function () {
        alert(self.id);//content
    })
});

15.new操纵符

在JavaScript中,经由历程new操纵符来作用于一个函数,本质上会发作如许的行动。

起首,竖立一个空对象,然后用函数apply要领,将这个空对象传入作为apply的第一个参数以及上下文参数。如许函数内部的this将会被这个空的对象所替换。

var triangle = new Shape("triangle");
//上一句相当于下面的代码
var triangle = {};
Shape.apply(triangle, ["triangle"]);

16.用JavaScript函数完成封装

function Person(name) {
    //私有变量
    var address = "1";

    //大众要领
    this.getAddress = function () {
        return address;
    };

    //大众变量
    this.name = name;
}

//大众要领
Person.prototype.getName = function () {
    return this.name;
};

//大众要领
Person.prototype.setName = function (name) {
    this.name = name;
};

起首声明一个函数,作为模板,用面向对象的术语来说,就是一个类。用var体式格局声明的变量仅在类内部可见,所以address为一个私有成员,接见address的唯一要领就是经由历程我们向外暴露的getAddress要领,而get/setName,均为原型链上的要领,因而为公然的。我们能够做个测试:

var jack = new Person("jack");
console.log(jack.name);//jack
console.log(jack.getName());//jack
console.log(jack.address);//undefined
console.log(jack.getAddress());//1

增加静态变量:

function Person(name) {
    //私有变量
    var address = "1";

    //大众要领
    this.getAddress = function () {
        return address;
    };

    //大众变量
    this.name = name;
}

Person.TAG = "javascript-core";//在接见该变量的时刻,不须要实例化Person类

17.函数式的JavaScript

函数能够坚持本身内部的数据,函数的运算对外部无副作用(修改了外部的全局变量的状况等)。关于函数能够坚持本身内部的数据这一特征,成为闭包。示例:

var outter = function () {
    var x = 0;
    return function () {
        return x++;
    }
};

var a = outter();
console.log(a());//0
console.log(a());//1
console.log(a());//2

var b = outter();
console.log(b());//0
console.log(b());//1

变量a经由历程闭包援用outter的一个内部变量,每次挪用a()就会转变此内部变量,应当注重的是,当挪用a时,函数outter已返回了,然则内部变量x的值依然被坚持。而变量b也援用了outter,然则这是一个差别的闭包,所以b最先援用的x值不会跟着a()被挪用而转变,二者有差别的实例,这就相当于面向对象中的差别实例具有差别的私有属性,互不干涉。

18.柯里化的观点

柯里化就是预先将函数的某些参数传入,获得一个简朴的函数,然则预先传入的参数被保存在闭包中,因而会有一些奇异的特征。比方:

var adder = function (num) {
    return function (y) {
        return num + y;
    }
};

var inc = adder(1);
var dec = adder(-1);

console.log(inc(99));//100
console.log(dec(101));//100

19.函数式编程作风

一般来说,函数式编程的谓词(关联运算符,如大于、小于、即是的推断等),以及运算(加减乘除等)都邑以函数的情势涌现,比方:

a > b

一般示意为:

gt(a, b)

因而,能够起首对这些罕见的操纵举行一些包装,以便我们的代码更具有“函数式”作风。

假如我们之前的编码作风是如许:

//阶乘
    function factorial(n) {
        if (n == 1) {
            return 1;
        } else {
            return n * factorial(n - 1);
        }
    }

在函数式作风下,就应当是如许了:

    function factorial(n) {
        if (equal(n, 1)) {
            return 1;
         } else {
             return mul(n, factorial(dec(n)));
         }`
    }

20.运动对象

在JavaScript中,当一个函数被挪用的时刻,就会发生一个特别的对象:运动对象。这个对象中包含了参数列表和arguments对象等属性。由于运动对象是变量对象的惯例,因而,它包含变量对象一切的属性,如变量定义,函数定义等。

实例:

function func(handle, message) {
    var id = 0;

    function doNothing(x) {
        return x;
    }

    handle(message);
}

func(print, "hello");//实行到这里的时刻,运动对象被竖立

21.作用域链

作用域链与原型链相似,也是一个对象构成的链,用以在上下文中查找标识符(变量、函数等)。查找时也与原型链相似,假如激活对象本身具有该变量,则直接运用该变量的值,不然向上层搜刮,顺次类推,直到查找到或许返回undefined。作用域链的重要作用是用以查找自在变量。所谓自在变量是指,在函数中运用的,非函数内部部分变量,也非函数内部定义的函数名,也非情势参数变量。这些变量一般来自于函数的“外层”或许全局作用域,比方,我们在函数内部运用的window对象及其属性。

var topone = "top-level";
(function outter() {
    var middle = "mid-level";
    (function inner() {
        var bottom = "bot-level";
        console.log(topone + ">" + middle + ">" + bottom);
    })();
})();
//在函数Inner中,console.log语句涌现的topone、middle变量就是自在变量

22.词法作用域

在javascript中,函数对象的竖立和函数本身的实行是完整差别的两个历程。

function func() {
    var x = 0;
    console.log("func");
}//这是函数的竖立
func();//函数的实行

所谓词法作用域(静态作用域)是指,在函数对象的竖立时,作用域就已竖立,而并非到实行时,由于函数竖立后能够永久不会被实行,然则作用域是一直存在的。比方在上例中,假如在顺序中没有挪用func(),那末,func对象仍旧是存在的,在内存的组织多是如许的:

func.["[[scope]]"] = global.["variable object"];

而当函数实行时,进入函数实行期上下文,函数的运动对象被竖立,此时的作用域链是运动对象和”[[scope]]”属性的合成。

23.this的上下文

this值是实行期上下文对象的一个属性(实行期上下文对象包含变量对象、作用域链以及this)。实行期上下文对象有三类,当进入差别的上下文时,this的值会肯定下来,而且this的值不能变动。在实行全局代码时,掌握流会进入全局实行期上下文,而在实行函数时,又会有函数实行期上下文。比方:

var global = this;
var tom = {
    name: "Tom",
    home: "desine",
    getInfo: function () {
        console.log(this.name + ", from " + this.home);
    }
};
tom.getInfo();
var jerry = {
    name: "Jerry",
    getInfo: tom.getInfo
};
jerry.getInfo();

global.getInfo = tom.getInfo;
global.getInfo();
输出效果:
    Tom, from desine
    Jerry, from undefined
    , from undefined

tom对象本身具有name和home属性,因而在实行tom.getInfo时,会打印tom对象上的这两个属性值。当将global.getInfo属性设置为tom.getInfo时,getInfo中的this值,getInfo中的this值,在运转时,现实上是global对象,所以name和home均未定义。

24.window对象

window对象是对浏览器当前窗口的援用,由于浏览器会将window与本身绘制出来的窗口绑定起来,我们对window的操纵现实上会映射到浏览器窗口上。恰是浏览器本身供应了这类剧本化的才能,我们才有时机经由历程JavaScript代码来完成许多操纵。

25.文档对象模子(DOM)

DOM即文档对象模子,它是一个平台,供应言语无关的API,许可顺序接见并变动文档的内容、组织以及款式。HTML文档是一个树形的组织,与浏览器中的页面中的组织一一对应。

26.事宜驱动模子

由于客户端JavaScript的开辟属于用户界面开辟的领域,因而运用事宜驱动模子就显得异常天然了。事宜驱动的特性在于:代码块的运转与否与顺序流程无关。而传统的流式代码的特性是,从函数的进口进入,顺次挪用各个子模块的处置惩罚函数,末了退出。这类编程形式重要适用于与UI关联不大的场所,很少有异步的历程,这些特性能够要追溯到盘算机顺序的最初模子——批处置惩罚。

而事宜驱动模子重如果面向用户的,你没法晓得用户会怎样运用你的顺序,因而就只能经由历程回调、事宜监听等体式格局,当用户做出某个行动时才会触发之前已注册好的监听器,从而实行相干代码,而不是递次地实行。甚至在一次运转中,部份代码一直没有被触发,也就基础不会被实行到。

27.与效劳器端交互(Ajax)

Ajax示意异步JavaScript与XML。现实上,Ajax与XML几乎没有任何关联,由于是异步交互,所以用户的页面不必革新,在同一个页面中,客户端要求效劳数据,当效劳数据返回时,经由历程JavaScript将数据片断填充到页面的某个部份,即完成了部分革新。

    原文作者:Gideon
    原文地址: https://segmentfault.com/a/1190000005944355
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞