啃一啃犀牛书--类型、值、变量(2)

啃一啃犀牛书–类型、值、变量(2)

接着前面的来,前面只说了一半。

不可变的原始值和可变的对象引用

听起来比较绕口。js的原始值(undefined,null,boolean,number,string)是不可更改的。

1
2
3
var s = 'javascript';        //javascript
s.toUpperCase(); //JAVASCRIPT
s //javascript

关于对象,里面有一个有趣的比较:

1
2
3
4
5
6
var a = {x:1};
var b = {x:1};
a===b //false! 两个单独的对象永不相等
var c = a;
var d = a;
c===d //true!c,d 引用同一个对象。

类型转换

在前面简单的提到了一点,在犀牛书49页,有一个javascript类型转换的一个表格,有必要看一下哦~
这里面有一句话,可以注意一下的:

需要特别注意的是,一个值转换成另外一个值并不意味着两个值相等。例如,如果再期望使用布尔值的地方使用了undefined,它将转换成false,但这并不表名
undefined==false。

显示类型转换:

  • Boolean()
  • Number()
  • String()
  • Object()

    在javascript中对象转化为字符串经历了什么样的步骤呢?

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

  • 如果对象没有toString()方法,或者这个方法并不返回一个原始值,那么js会调用valueOf()方法。如果存在这个方法,js调用它。如果返回值是原始值,js将这个值转换成字符串。
  • 否则,js无法从toString()或valueOf()获得一个原始值,因此这是它将抛出一个类型错误的异常。

同理看对象转化成数字。(会先尝试使用valueOf()方法)

  • 如果对象具有valueOf()方法,后者返回一个原始值,将这个原始值转换成数字并返回。
  • 否则如果对象具有toString()方法,后者返回一个原始值,将这个原始值转换成数字并返回。
  • 否则,抛出一个类型错误异常。
变量声明

在es5,我们声明变量基本上只有两种方法:var,function。在es6中又添加了let,const,import,class。现在es6基本上大家都在用了,我们也不要out了。
但是我们在使用的时候,这里面还是有一点小坑的,具体可以移步ECMAScript6入门

变量作用域

这个应该算是js面试必考的一个问题了。这里面有几个要点:
在函数体内,局部变量的优先级高于同名的全局变量。

变量在声明他们的代码段之外是不可见的,我们成为块级作用域,而js中并没有块级作用域,js取而代之地使用了函数作用域:变量在声明他们的函数体外以及这个函数体嵌套的任意函数体内都是有定义的。
但是在es6中,let,const实际上相当于为js新增了块级作用域。
在这里就比较容易解释变量提升了,但是也还是要注意,var定义的变量是存在变量提升的,但是let,const定义的变量不存在变量提升。
var定义变量允许我们进行重复的定义,但是let,const是不需要重复定义同一个变量的。

作为属性的变量
1
2
3
var a = 1;
var a = 2;
let a = 3; //Identifier 'a' has already been declared

上面这个代码,最后一行是会报错的。我是在浏览器的控制台进行输入的,这里的a其实也就是window.a。
我们的a并不在任何函数的内部,这是一个全局变量,而这个全局变量实际上相当于window的一个属性。同样也可以直接通过this来引用全局对象。

作用域链

它对于我们理解闭包是很有帮助的。所以在理解闭包的时候,再返回来看一下,相信记忆会更深刻。