一.对象
对象由下面这三种方式创建:
- 对象字面量
- 来自构造函数的对象
- 来自自定义构造函数的对象
对象字面量
在大括号里面写上键值对,键和值之间以分号分割,不同的键值对以逗号分隔。这种方式就是字面量。值可以是任意类型对象,除值是函数外我们都称为属性。值是函数我们称为方法。
1 | // 创建对象 |
来自构造函数的对象
可以使用类似 Object(), Date(), String()的内置构造函数来创建对象。
1 | var obj = new Object(); |
但是这种方式是不推荐的, 原因:
在构造时,解析器需要从调用Object()的位置开始一直向上查询作用域链,直到发现全局的object函数(可能以同样的命名创建了一个局部构造函数)—>但字面量并没哟作用域解析。
使用内置构造函数来创建对象。对于不同的内置函数会有自己的特征。例如:Object()构造函数会接受一个参数。并且以来传递进来的参数,导致Object()会委托其他的内置函数来创建对象,并且返回一个并非期望的函数
1
2
3
4
5
6
7
8
9
10
11
12
13var o = new Object();
console.log(o.constructor === Object) // true
o = new Object(1)
console.log(o.constructor === Number) // true
console.log(o.toFixed(2)) // 1.00
var o = new Object('tss');
console.log(o.constructor === String) // true
console.log(typeof o.substring()) //Object并没有substring方法。但是字符串是由的。
var o = new Object(true);
console.log(o.constructor === Boolean) // true
自定义构造函数创建的对象
1 | var Person = function(name) { |
使用new 操作符调用构造函数(自定义+内置)时。函数内部发生的事:
- 创建一个空对象.
- this指向该空对象.并且继承函数的原型。
- 属性和方法被加入到this引用的对象中
- 新对象由this值引用,并且最后隐式的返回(如果没有显示的返回值)
1 | var Person = function(name) { |
使用new操作符创建对象时,构造函数总会返回一个对象。默认情况下返回的是this所引用的对象。如果在构造函数中不向this添加任何属性和方法,将会返回一个空对象(这里的”空”,实际上并不空,它已经从构造函函数的原型继承了很多成员)。
当然构造函数你可以返回你想要的信息。
1 | var Person = function(name) { |
注意:在用new操作符创建对象时,构造函数总会返回一个对象。默认情况下返回的时this所引用的对象。如果在构造函数中没有向this添加任何属性和方法。那么将返回一个空对象(除了从构造函数的原型继承的成员)
构造函数将隐式的返回this。甚至在函数中没有显式的加入return语句。但是可以根据需要返回任意其他对象。
强制使用new的模式
构造函数也是函数,只不过它却以new的方式调用。如果在调用构造函数时忘记添加new操作符会发生?这虽然不会导致语法和运行时的错误。但是可能导致逻辑错误和意外的行为发生。忘记加new操作符。导致构造函数的this指向全局对象。
1 | // 自定义构造函数 |
解决的办法
命名约定。使构造函数的函数名首字母是大写的。有助于在一定程度上能避免忘记new操作符。
构造函数不使用this。构造函数中并不用将方法和属性添加到this。而是添加到一个自定义的变量,最后返回。甚至不需要一个这样的局部变量。直接返回一个对象即可。
1
2
3
4
5
6
7
8
9
10function name() {
return {
name: "shuliqi"
}
}
var firstName = new name();
var secondtName = name();
console.log(firstName.name) // "shuliqi"
console.log(secondtName.name) // "shuliqi"但是这种方式的缺点是会丢失到原型的链接。构造函数的原型属性都是不可用的。
自调用构造函数
为了使得构造函数的属性在实例对象中也能使用。可以在构造函数中检查this是否为构造函数的实例。如果为否。可以再次调用自身。并且在这次调用中正确的使用了new操作符。
1
2
3
4
5
6
7
8
9
10function name() {
if(!(this instanceof name)) {
return new name;
}
this.name = "shuliqi";
}
name.prototype.age = 12;
var newName = name();
console.log(newName.name,newName.age) // "shuliqi", 12另一种检测实例对象的方法是使用arguments.callee进行比较。callen属性指向被调用的函数。这样就不用在编码的时候硬编构造函数的名字了。
1
2
3
4
5
6
7
8
9
10function name() {
if(!(this instanceof arguments.callee)) {
return new name;
}
this.name = "shuliqi";
}
name.prototype.age = 12;
var newName = name();
console.log(newName.name,newName.age) // "shuliqi", 12
二.数组
数组对象可以通过下面这三种方式创建:
数组字面量表示法:逗号分隔的元素列表。并且元素列表包装在一个方括号中。可以给元素指定任意类型的值。包括对象或者其他数组。
1 | var arr = ["1", "2", "3"] |
数组构造函数
可以通过内置的构造函数Arrry()来创建数组
1 | var arr = new Array("1", "2", "3") |
注意:最好不要使用构造函数来创建数组。因为当向构造函数传递单个数字时,它并不会成为数组的第一个元素的值。而是设置了数组的长度。但是数组中并没有实际的元素。
1 | var arr = [3]; |
如果传入的是浮点数将会更糟糕
1 | var arr = [3.14]; |
因此坚决使用字面量将使程序更加安全。
检查数组的性质
因为以数组为操作数的并且使用typeof操作符。结果都会返回”object”。
检查一个对象是否是数组的办法:
可以检查对象是否存在数组的一些属性(length)和方如slice(),split()等。以此来确定该值是否具有”数组性质”。
缺点:不能保证任何其他非数组对象不能具有相同名称的属性和方法。
instance Array进行检查
缺点:在某些浏览器版本中的不同框架运行并不正确。
ES5中的Array.isAarray()方法。该函数在参数为数组的时候返回true
1
2
3
4
5
6
7console.log(Array.isArray([])) // true
// 尝试以一个类似数组的对象欺骗检查
console.log(Array.isArray({
length: 1,
slice: function() {}
})) // false如果无法使用rray.isAarray()方法, 可以通过调用Object.prototype.toString()方法进行检查。如果在数组上,详细问调用toString()的call()方法,它应该返回”[object Array]”。如果是上下文是对象,则它应该返回字符串”[object object]”。
1
2
3
4
5if (typeof Array.isArray === 'undefined') {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === "[object Array]";
}
}
JSON
JSON是一种轻量级的数据交换格式。是一个数组和对象字面量表示方法的结合。
1 | { "name": 'shu', "age": 23, "some": [1, 2, 3]} |
JSON文字对象之间的区别
在JSON中,属性名称需要在包装在引号才能成为合法的JSON。
在对象字面量中。仅当属性名称不是有效的标识符的时候菜会需要使用引号。例如:
1 | {"first name": "jsdhs"} |
注意: 在JSON中不能使用正则表达式字面量和函数。
使用JSON
使用JSON.parse()解析字符串。
使用JSON.stringify()将基本数据类型序列化成为一个JSON数组。
正则表达式
正则表达式也是对象,可以通过两种方式创建正则表达式:
- 使用正则表达式字面量
- 使用new RegExp()
使用正则表达式字面量
正则表达式字面量表示法使用了些刚(”/“)来包装用于匹配的正则表达式模式。在第二个斜杆之后,可以将该模式修改为不加引号的字母形式。
1 | var reg = /shuliqi/gm |
使用new RegExp()
1 | var reg = new RegExp("shuliqi", "i") |
能使用久使用字面量。
基本值类型包装器
javascript中的基本数据类型:number,string, boolean,null, undefined。除了null和undefined,其他三个具有所谓的基本包装对象。可以使用内置构造函数Number(),String()和Boolean()创建包装对象。
1 | // 一个基本数值 |
基本值只要调用包装对象的方法,就可以在后台杯临时转换为一个对象,并且表现得犹如一个对象。
1 | // 用来作为对象的基本字符串 |
由此可看出:基本值也可以充当对象,只要需要他们这么做。但是通常没有理由去使用更长的包装构造函数。
通常使用包装对象的原因之一是有扩充值及持久保存状态的需要。这是由于基本类型不是对象,他们不可能扩充属性
1 | // 基本字符串 |