JavaScript小白学习笔记4——实战案例

JavaScript基础知识的最后一节。本节主要是一些实战上用到的一些基础内容。

k6dudI.md.jpg


检测数据类型

typeof运算符能够检测数据类型,其返回一个用于识别操作数类型的字符串。对于任何变量来说,typeof运算符总是以字符串的形式返回以下六种类型之一:

number
string
boolean
object
function
undefined

不幸的是,在使用typeof检测null值时,返回的是object,而不是“null”。更好的检测null的方式其实很简单,下面定义一个检测值类型的一般方法,

1
2
3
function type(o) {
return (o == null) ? "null" : (typeof o);
}

对于对象或数组可以使用constructor属性,该属性值引用的是原来构造该对象的函数,如果结合typeof运算符和constructor属性,基本能够完成数据类型的检测。

使用属性可以判断绝大部分数据的类型,但是对于undefinednull特殊值就不能使用constructor属性,使用则会抛出异常,此时可以先把值转换为布尔值,如果为true则说明不是undefinednull值,然后再调用属性。

对于数组直接量也不能使用constructor属性,需要加上一个小括号,这是因为小括号运算符能够把数值转换为对象。

使用toString()方法,检测对象类型是最安全最准确的。调用toString()方法把对象转换为字符串,然后通过检测字符串中是否包含数组所特有的标志字符,可以确定对象的类型。该方法返回的字符串格式如下:

[object class]

其中,object表示对象的通用类型,class表示对象的内部类型,内部类型的名称与该对象的构造函数名对应。

class值提供的信息与对象的,constructor属性值想死,但是class值是以字符串的形式提供这些信息的。而不是以构造函数的形式提供这些信息的,所以在特定的环境中是非常有用的。

但是要获取对象的class值的唯一方法是必须调用object定义的默认toString()方法,因为不同对象都会定义自己的toString方法,所以不能直接调用对象的toString方法。要调用Ojbect对象定义的默认toString()方法,可以先调用Object.prototype.toString对象的默认toString函数,再调用该函数的apply()方法在想要检测的对象上执行。

综上,我们可以得到一个比较完整的数据类型安全检测方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
function typeOf(o) {
var _toString = Object.prototype.toString();
//获取对象的toString方法引用
//列举类型和内置对象类型,可以进一步补充该数组的检测数据类型范围
var _type = {
"undefined" : "undefined",
"number" : "number",
"boolean" : "boolean",
"string" : "string",
"[object Function]" : "function",
"[object RegExp]" : "regexp",
"[object Array]" : "array",
"[object Date]" : "date",
"[object Error]" : "error"
}
return _type[typeof o] || _type[_toString.call(o)] || (o ? "object" : "null");
}

数值计算与类型转换

JavaScript在执行数值运算时,常会出现浮点数溢出的问题,比如0.1+0.2不等于0.3。。。

由于存在这种bug,一般在对小数进行运算时要去指定精度,因为JavaScript小数的整数运算还算精确。例如,元可以通过乘以100来转化成分,然后再进行计算,最后将结果转化为元。

JavaScript能够自动转换数据类型,这种转换操作是一种隐式的行为。

如果把非空对象用在逻辑运算环境中,则对象被转换为true,此时的对象包括所有类型的对象,即使值为false的包装对象也转换为true。

如果把对象用在数值运算环境中,则对象会被自动转换为数字,如果转换失败,则返回值NaN。

当数组被用在数值运算环境中,数组将根据包含的元素来决定转换的值,如果数组为空数组,则被转换为数值0,如果数组仅包含一个数字元素,则被转化为该数字的数值,如果数值包含多个元素,或者仅包含一个非数字元素,则返回NaN。

当对象用于字符串环境中时,JavaScript能够调用toString()方法,把对象转换为字符串,再进行相关计算。当对象与数值进行加运算时,则会尝试将对象转换为数值,然后参与求和预算。如果不能够将对象转换为有效数值,则执行字符串连接操作。

字符串替换

使用字符串的replace()方法可以实现字符串替换操作。该方法包含两个参数:第一个参数表示执行匹配的正则表达式,也可以是字符串,第二个参数表示准备代替匹配的字符串。

比如,下面的操作把top换成xyz:

1
2
var a = "shawnzhou.top";
var b = a.replace("top","xyz");

replace方法同时执行查找和替换两种操作。该方法将在字符串中查找与正则表达式相匹配的字符串,然后调用第二个参数值或替换函数来替换这些字符串。如果正则表达式具有全局性之,那么将替换所有的匹配字符串。否则,只替换第一个匹配的字符串。

(我并不会正则表达式。。。当时学Python的时候怎么就没认真学呢qwq)

在replace()方法中有一个特殊的$符号,它有一些特殊的用法。

下面有一个简单的例子:

1
2
3
var a = "awslsdl";
var b = a.replace(/(awsl)(sdl)/,"$2,$1");
alert(b);

这里第一个参数便是代表一个正则表达式,它被放在两个/里面。每一对小括号都代表一个子表达式,从1开始编号。在替换时$1,$2可以用来作为一个子表达式的引用。当然它们不是标识符,仅仅是一个标记,所以不能用来参与运算。

关于$的用法:

$+数字,比如$1,$2之类的,代表引用第几个子表达式。
$&,代表与正则表达式相匹配的字符串。
$` 代表位于匹配字符串左侧的文本。
$’ 代表位于匹配字符串右侧的文本。
$$ 代表一个$号。

一个简单的示例:

1
2
3
var a = "awslsdl";
var b = a.replace(/.*/,"$&$&");
alert(b);

$&代表的是正则表达式匹配的文本,但是这个正则表达式长得有点????

/.*/这是什么鬼?

它代表完全匹配字符串。也就是整个串。所以使用$&就可以开心的当个复读机啦(误

那这个左侧右侧是怎么操作的呢?再给出一个例子:

1
2
3
var a = "老婆饼里没有";
var b = a.replace(/饼里没有/,"$&$`");
alert(b);

可以看出,这里的左右是相对于正则表达式匹配的字符串。

在ECMAScript3中明确规定,虽然没有禁止使用字符串,但是replace()方法的第二个参数建议使用函数,而不是字符串。这样当replace()方法执行匹配时,每次都会调用该函数,函数的返回值将作为替换文本执行匹配操作。同时函数可以接收以$为前缀的特殊字符组合,用来对匹配文本相关的信息进行引用。

实际上,replace()方法的第二个参数的函数的参数是很含蓄的(含不含蓄我不清楚,反正够绕的),即使不传递任何形参,replace方法依然会向它传递多个实参,这些实参都包含一定的意思。

(这种传函数或者说是传一堆参数的操作过于繁琐,先放放,用到再说)

数组花式排序

我们知道,使用sort方法可以对数组进行排序,如果为方法传入一个比较函数,那它就可以根据其他顺序执行操作了。

比较函数的写法和C++中自定义比较函数写法比较类似,需要定义两个参数a和b,然后返回一个用于说明这两个值相对顺序的数字。

如果根据自定义评判标准,a小于b,在排序后的数组a应该出现在b之前,那就返回一个小于0的值。

如果a和b相等,返回0。

如果a大于b,则返回一个大于0的值。

怎么说?a小于b的时候要让a排在b前面?这不就是从小到大排么,升序排序啊这是。此时应该返回一个小于0的值,怎么操作?返回a-b就好了啊。

如果要降序排序呢?那就返回b-a啊。。。。。qwq

这时候你可能会说了,这算什么花式排序?

坐好了,下面才是正片。

第一招:对函数按照奇偶数进行排序

以奇数在前偶数在后为例,首先需要自定义一个函数判断奇偶数,然后决定排列顺序。调用比较函数时,将每个元素值传递给比较函数,如果元素值为偶数,则保留其位置不变,如果元素值为奇数,则调换参数a和b的显示顺序,从而实现对数组中所有元素进行奇偶排序。

1
2
3
4
5
6
7
8
function f(a, b) {
var a = a % 2;
var b = b % 2;
if (a == 0)
return 1;
if (b == 0)
return -1;
}

如果要让偶数在前,奇数在后,直接把两个返回值对调即可。

啥?这样做不能同时排大小?这个留给你自己操作吧(滑稽

第二招:不区分大小写排序字符串

在正常情况下,对字符串的排序是区分大小写的,这是因为每个大写字母和小写字母的ASCII值通常是不同的。大写字母要排在小写字母的前面。

也就是说,大写字母总是排在左侧,而小写字母总是排在右侧。如果让小写字母总是排在最前面,则可以按如下设计:

1
2
3
function f(a ,b) {
return ( a < b );
}

对,就这么简单。

实际上,在比较字母大小时,JavaScript是按照字母的ASCII值进行排序的。当比较函数的返回值为true时返回1,false返回-1。如果不希望区分字母大小,那就直接把大写字母转换成小写字母就好了嘛!

(别打我)

1
2
3
4
5
6
7
8
9
10
function f(a, b) {
var a = a.toLowerCase();
var b = b.toLowerCase();
if (a < b) {
return 1;
}
else {
return -1;
}
}

第三招:把浮点数和整数分开排列

1
2
3
4
5
6
function f(a, b) {
if (a > Math.floor(a))
return 1;
if (b > Math.floor(b))
return -1;
}

这样写就会让整数在前,浮点数在后。当然,反过来的话只需要让返回值反过来就好。

小结

emmm从年后开始学JavaScript,断断续续的学了一个周左右吧,怎么感觉收获不算多呢?大概学到这里只能算浅尝辄止吧,Java也是,只能算入门,撇去ACM不管的话Java也只是一个入门。不过至少掌握了基本的规则。之后要怎么发展全看自己,这就算当一个底子了。

填完这个坑发现,寒假还有一些坑没填完。要加快进度了。


-------------本文结束,感谢您的阅读转载请注明原作者及出处-------------


本文标题:JavaScript小白学习笔记4——实战案例

文章作者:Shawn Zhou

发布时间:2019年02月14日 - 17:02

最后更新:2019年02月18日 - 13:02

原始链接:http://shawnzhou.xyz/2019/02/14/19-02-14-02/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

知识无价,码字不易。对您有用,敬请打赏。金额随意,感谢关心。
0%