js基础-类型、值和变量(中)

/ 0评 / 1

9.正则表达式

首先,js定义了RegExp()构造函数,用来创建表示文本匹配模式的对象。这就是正则表达式。正则表达式并不是js的基本类型,它和Date(日期)一样,只是一种具有实用API(应用程序接口)的特殊对象。它是一种强大的文本处理工具。有丰富的API。

js里的正则表达式具有直接量的写法。例如

var pattem=/abc/

在两条斜线之间的文本构成一个正则表达式直接量。第二条斜线之后可以带有字母参数,代表用来修饰模式的含义,正则表达式的语法是

/正则表达式主体/修饰符(可选)

例如

var pattem=/abc/i   //i表示不区分大小写    g表示执行全局匹配   m执行多行匹配

RegExp对象定义了很多有用的方法,字符串同样具有接受RegExp参数的方法,这里我们先说一下,我们先知道js也有这个东西就可以了,以后的时候会更加详细的研究这个正则表达式,因为正则表达式是非常强大的。

10.布尔值

何为布尔值,非常好理解,布尔值只有两个值,真(true)或者假(false)js程序中的比较语句通常都是布尔值,比如

a==1;

如果啊=1,那么a==1就是true,否则就为false.布尔值通常用在循环控制结果中,例如if/els语句等

if(flag){
//dosomthing
}else{
//doanohting
}

如果flag转换成布尔值为true,就执行//dosomething代码,否则就执行//doanothing代码。从上面可以知道,js还有个转换功能,要知道,任意js的值都可以转换成布尔值,如果转换为true的话我们称之为真值,如果转换为false的话,我们称之为假值,例如下面这些只会被转换成false

undefined
null
0
-0
NaN
"" //空字符串

所有其他的值,包括对象(数组)都会转换成true

11.null和undefined

null是js的关键字,表示一个特殊字,常用来描述“空值”,它也是一个对象,只是表示的是“非对象”,它是它自由类型的唯一一个成员,例如

console.log(typeof null) //object typeof是一个操作符,能够判断所操作值的类型

undefined是表示“未定义”,它是变量的一种取值,表明变量没有初始化,多种情况下能返回undefined

  1. 如果要查询不存在的对象属性或者不存在数组元素
    2.函数没有返回值的时候,返回undefined
    3.引用没有实参的函数形参的值(关于函数实参(实际参数)和形参(形式参数),这里简单说下 比如定义一个函数 function fn(a){console.log(a);}a就是函数的形参,调用函数fn(2) 2就是函数的实参)
  2. undefined是预定义的全局变量,它的值就是未定义,要记住undefined是只读的。

null和undefined的关系

null==undefined //true
null===undefined false

相当运算符(==)认为他们是相同的,全等运算符(===)则任务他们是不相等的他们都不包含任何属性和方法,,如果,我们要预定义一个变量,并且不知道这个变量的类型的话,选择null是最佳的。
例如

var a=null; //表示值的空缺

12.全局对象

对象中还有一类很重要的对象,那就是全局对象,当js解析器启动的时候,或者wen浏览器加载新页面的时候,会创建一个新的对象,并给他一组定义的初始属性

全局属性,比如undefined、NaN等
全局函数 alert() isNaN()等
构造函数 Date()、RegExp()、String()等

 

在代码的最顶级,不在任何函数内的js代码,可以用js关键字this来引用全局对象

var win=this;

而在浏览器中,Window对象充当了全局对象。当初次创建的时候,全局对象定义了js中所有预定义全局的值。如果代码声明了一个全局变量,这个变量就是全局对象的一个属性

var a=1;
console.log(window.a) //1

console是属于全局对象的,只是浏览器中,我们可以忽略window,

window.alert(window.a) //1
window.console.log(a) //1

13.包装对象

js的对象是属性或者已命名值的集合,通过“.”符号来引用属性值,当属性值是一个函数的时候,称之为方法,通过o.m()来调用对象o中的方法。但是,我们看到字符串也同样具有属性和方法,例如

var str="abc123";
var str2=str.indexOf(' ');
str.length;
str2.length;
为什么字符串既然不是对象,那它还会有属性和方法了。
原来是,只要引用了字符串str的属性或者方法,那么js就会将字符串值通过条用new String(str)的方式转成对象。而这个由str转换而来的对象继承了字符串的方法,并被用来出来属性的引用,一旦属性引用结束后,这个对象就会被销毁,这个对象,我们可以先暂时叫他临时对象,是用来处理对其的属性引用的。
var a="123123";
a.len=6;
console.log(a.len); //undefined

当运行结果后,a.len的值为undefined。这样是不是会很疑惑,是这样的,代码在读取字符串,数字和布尔值的属性或者方法的时候,其表现的形式就像对象一样。但是如果试图给其属性赋值的话,则会忽略这个操作,要记得,修改只是发生在临时对象上,而这个临时对象并未继续保留下来,它只是在读取的时候被创建后又被销毁了。

同字符串一样,数字和布尔值也具有各自的方法,通过Number()、Boolean()构造函数创建一个临时对象,这些方法的调用均来自这个临时对象。 null和undefined没有这个对象,所以访问它们的属性和抛出类型错误。

在读取字符串、数字或者布尔值的属性时创建的临时对象称作包装对象,只是用来区分字符串值和字符串对象、数字和数值对象、布尔值和布尔对象。一般来说,包装对象只是被看作以一种实现的
细节,由于他们只是只读的,并且不能给他们定义新属性,因此他们是有别于对象的。

js会在必要的时候将包装对象转换成原始值,“==”运算符将原始值和其包装对象视为相等,“===”则视为不相等。
通过typeof运算符可以看到原始值和其包装对象的不同

var a=new String('123');
var b="123";
console.log(a);
console.log(b);
不可变的原始值和可变的对象引用

js的原始值(undefined、null、布尔值、数字和字符串)和对象(包含数组和函数)的根本区别就是,原始值是不可更改的,但是对象的值是可更改的比如

4=5
false=true;

改变数字本身就说不通了,对于字符串来说,我们要知道,因为字符串看起来像有字符组成的数组,我们通过字符串方法修改字符串中的字符不就是改变了原始值了吗?不就改变了原始值了吗?
实际上是这样的,通过字符串方法修改的是返回一个新的字符串,而原先的字符串还是没有修改的

var text="hello javascript";
var text2=text.replace(/l/g,'');
console.log(text);
console.log(text2);

我们用replace()将textd的“l”字符替换成空,但是我们输出text的话,发现text还是没有改变的,只是操作text后返回了一个新的字符串。

js的原始值的比较是通过值的对比,只有它们的值相等时候它们才相等,当然了,对于除了字符串外的原始值有点难懂了,因为没有其他方法可以直接来比较他们。当时对于字符串来说,当且仅当
两个字符串的长度相等并且每个索引的字符都相等的时候,js才认为他们是相等的。

对象和原始值不一样,它们的值是可以修改的
var obj={a:1} //定义一个对像obj,并且obj有个a属性等于1
obj.a=2; //改变obj.a的值
obj.y=3; //为obj赋予新的属性y,并且y=3

console.log(a);
console.log(obj);

var arr=[1,2,3,4]
a[0]=0; //更改数组元素
a[4]=5; //给数组增加一个新元素

对象的比较,并非是比较值,即使两个对象包含同样的属性同样的值,索引元素完全相等两个对象也是不相等的。因为对象是引用类型,何为引用呢?简单的来说就是要给指针,指向内存中的某一个对象。而对象的比较实际上是引用的比较,当它们引用同一个对象的时候,它们才相等。

var obj={x:1};
var obj2=obj;
obj.x=2;
console.log(obj2.x);

上面代码运行可知道,给对象或者数组赋值一个变量,仅仅只是复制了引用值,对象本身并没有赋值了一份,它们还是共同引用同一个对象,当用引用值取修改对象的时候,对象就已经发生修改了,所以所有引用了该对象的都会被修改了。

当然了,如果我们需要赋值对象的一个副本,而不是仅仅只是赋值引用,我们可以遍历对象的属性和方法,将它们复制放到一个新的对象中。以后我们会更深入探究。
例如,数组复制

 

var arr=['1','2','3'];
var arr2=[];
avr i;
for(i=0;i<arr.length;i++){ //遍历数组arr中的每一个元素
   arr2[i]=arr[i] //将元素值复制到arr2数组中
}

当然我们也来看下比较两个数组的函数

function equalArr(arr1,arr2){ //定义函数 用function 关键字 +函数名(参数){//具体实现}
    if(arr1.lenght!=arr2.length){return false} //当两个数组的长度不一样的话函数就返回false 关于函数返回值的知识,我们以后渐渐会将,这个只要知道,一旦函数遇到return 的话就会结束执行返回false就说明两个数组不相等
    for(var i=0;i<arr1.length;i++){ //当arr1和arr2长度相等时,遍历arr1和arr2的值进行对比
        if(a[i]!==b[i]){ //当发生有一项不相等的就终止函数,并且返回false,说明不相等
        return false; 
          }

    return true; //如果都满足上面条件的话,就证明这两个函数相等
    }
}

 

14.类型转换

js中的值的取值类型是非常灵活的,因为js是弱类型语言(https://www.zhihu.com/question/19918532),我们从之前的布尔值可以看到这一点,当js需要一个布尔值的时候,你就可以提供任意类型值,js将根据需要自行转换数据类型,真值转换成true,假值转换为false.这种转换在其他类型中也同样适用,如果js期望使用一个字符串,那么它就会把特定的值转换为字符串,其他类型也是如此。例如

console.log(1+“2”);     
console.log("7"*"4");
console.log(n-"x");
console.log(1+"object")

结果大家可以试一下,这里我们要注意的是,当把特定的值转换为数字的话,如果转换结果没有意义的话将会返回NaN,还有光宇+操作符,可以作为数字加号,也可以作为字符串连接符,当操作数有一个是为字符串的话,那它就会当作字符串连接符,而不是加号了

console.log("1" +2);
console.log("1"+"2");

从上面可以看出来,只要+号两边的操作符有一个是字符串的话,那+就是字符串连接符了。

我们参考《javaScript权威指南》书上的类型转换表可以来看一下哪些数据类型之间的转换规则,其中空单元格表示不必要也没有执行转换.

转换为字符串转化为数字转化为布尔值转化为对象
undefined“undefined”NaNfalsethrows TypeError
null"null"0falsethrows TypeError
true"true"1new Boolean(true)
false"false"0new Boolean(false)
""(空字符串)0falsenew String("")
“1”(非空,数字)1truenew String("1")
“one”(非空,非数字)NaNtruenew String("one")
0"0"falsenew Number(0)
-0"0"falsenew Number(-0)
NaN"NaN"falsenew Number(NaN)
Infinity(正无穷)"Infinity"truenew Number(Infinity)
-Infinity(负无穷)"-Infinity"truenew Number(-Infinity)
1"1"truenew Number(1)
{}(任意对象)参考下面内容参考下面内容true
[](任意数组)""0true
[9](1个数字元素)"9"9true
["a"](其他数组)"a"NaNtrue
function(){}(任意函数)参考下面内容NaNtrue

上表中的转换规则,我们可以知道,原始值到原始值的转换相对简单,转为为布尔值的我们已经在之前说过,真值转换为true,假值转换为false.转换为字符串的也可以明确可见了。转为为数字的:以数字表示的字符串可以直接转换为数字,也可以在开头和结尾中带有空格。但在开头和结尾的任意非空字符都不会被当作数字的一部分,进而转换为NaN.

原始值到对象的转换是通过调用String()、Number、Boolean()构造函数,转换为它们各自的包装对(关于包装对象可参考上面的内容)。

null和undefined属于例外,当它们用在期望是一个对象的地方都会造成一个类型错误(TypeError)异常,而不会执行正常转换,这是因为上面我们说过的,null和undefined上是没有定义任何方法和属性的,根本就不存在转换为对象的方法。

对象到原始值的转换是有点复杂的,现在我们来弄懂对象转换为原始值

对象转换到布尔值是非常简单的,只要记得,所有对象都转换为true,因为它们都是真值,对于new Boolean(false)是一个对象而不是原始值,所以他也转换为true。

对象到字符串的转换是通过条调用待转换对象的一个方法来完成的。当然了,js对象有两个不同的方法来执行转换的,并且要注意的是这里提到的字符串和数字的转换规则只适用于本地对象。

所有对象继承了两个转换方法。第一个是toString(),它的作用是返回一个反映这个对象的字符串

 var obj={x:1,y:2}
 console.log(obj.toString());

 var arr=[1,2,3];
 console.log(arr.toString());

 var fn=function(){alert(1);}
 console.log(fn.toString());

 var pat=/\d+/.toString()
 console.log(pat.toString());

 var date=new Date(2017,8,1);
 console.log(date.toString());

从上面可以知道,对像返回[object object],数组是将每个数组元素转换成一个字符串,并在元素之前添加逗号合并成结果字符串,而函数是返回这个函数的实现定义的表示方式(源码字符串),正则表达式则将其转换为表示正则表达式直接量的字符串,日期对象是返回了一个可读的日期和时间字符串。

另一个转换对象的函数valueOf()。应用《javaScript权威指南》中的话:这个方法的任务并未详细定义:如果存在任意原始值,它就默认将对象转换为表示它的原始值,对象是复合值,而且大多数对象无法真正表示一个原始值,因此默认的valueOf()方法简单的返回对象本身,而不是返回一个原始值。数组、函数和正则表达式简单的继承了这个默认的方法,调用这些类型的实力valueOf()方法只是简单返回对象本身。日期对象定义的valueOf()方法会返回它的一个内部表示:1970年1月1日以来的毫秒数(也就是时间戳)。

通过使用放过讲解的toString()和valueOf()方法,就可以做到对象到字符串和对象到数字的转换了。但是需要注意的是,在某些特殊的场景中,js执行了完全不同的对象到原始值的转换。这些特殊场景会一一探讨。

下面我们来总结下js种对象到字符串的转换步骤

1.如果对象具有toString()方法,则调用这个方法,如果它返回一个原始值,js将这个值转换为字符串(如果本身不是字符串的话),并返回了这个字符串结果

2.如果对象没有toString()这个方法,或者这个方法并不返回一个原始值,那么js会调用valueOf()方法。如果存在这个方法,则js就调用它,如果返回的是原始值,js会将这个原始值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。

3.否则,js无法从toString()何valueOf()获得一个原始值,因此这是他会抛出一个类型错误异常。对象到数字的转换过程中,js同样做了上面的事情,只是它会首先尝试使用valueOf()方法。

4.如果对象具有valueOf()方法,后者返回一个原始值,则js将这个原始值转换成数字(如果需要的话)并返回这个数字。

5.否则,如果对象具有toString()方法,后者会返回一个原始值,则就是会将其转换并返回

6.否则js抛出一个类型错误异常。

现在我们知道了为什么空数组会被转换成数字0以及为什么具有单个元素的数组同样会转换成一个数字。数组继承了默认的valueOf()方法,这个方法返回一个对象而不是原始值,因此,数组到数字的转换规则调用toString()方法,空数组转换成空字符串,空字符串转换成数字0.如果数组只包含一个数字元素,这个数字转换成字符串,在转换成数字。

js中的+运算符,如果它的操作书其中一个是对象,则js将使用特殊的方法将对象转换成原始值,而不是使用其他运算符的方法执行对象到数字的转换,==相等运算符于此类似,如果将对象与原始值进行比较的话。则转换将会按照兑现到原始值的转换方式进行。

当然也有特殊的情况了,就是日期类对象,Date是js语言核心中唯一预先定义的类型。它定义了有意义的向字符串和数字类型的转换。如果使用数字运算符,比如+进行日期对象的转换的话,日期对象则使用对象到字符串的转换模式,但是,这里的转换和上文讲述的并不完全一致:通过valueOf()或toString()返回原始值将被直接使用,而不会被强制转换成数字或字符串。

这里我们只要了解。除了日期对象的特殊情况,进行数字运算符的话,任何对象首先会尝试调用valueOf(),然后调用toString(),不管得到的原始值是否使用,它都不会进一步被转换成数字或字符串。例如

var a=[1,2,3];
var b=1;
console.log(a+b);

var obj={x:1,y:2};
console.log(b+obj);

显示类型转换和隐式类型转换

js有时候需要做显示砖会员,为了让代码变得清晰并且容易阅读。做显示转换最简单的方法就是使用Boolean()、Number()、String()或Object()函数,,它们会作为类型转换函数并按照之前说的那些规则做转换

Number('3');
String(false);
Boolean([]);
Object(3);

注意null和undefined没有toString()和valueOf()方法,如果转换成对象的话,会抛出类型错误,但是Object()函数在这种情况下不会抛出异常:它仅仅简单的返回一个新创建的类型转换。

var a=Object(null);
var b=Object(undefined);
console.log(a+" "+b);

js有显示类型转换,也有隐式类型转换,上面提到过数字运算符,比如+、-、*、/,还有!(取反操作符)等等

x+""   //等价与String(x);
+x     //等价于Number(x);
!x      //等价与Boolean(x);

Number类定义的toString()方法可以接受表示基(进制基数)的可选参数,如果不指定参数,则默认为十进制。

var num=20;
var  a=num.toString(2)   //转换为2进制
var  b=num.toString(8)   //转换为8进制
var  c=num.toString(16)   //转换为16进制

转换的就到这里了,下篇我们接着来学习js的变量延伸出来的知识了,谢谢观看,如果错误,欢迎指正!

简书求关注http://www.jianshu.com/u/bfd55badb1f4

欢迎讨论交流~

发表评论

电子邮件地址不会被公开。 必填项已用*标注