文章目录
  1. 1. 安全的类型检测
  2. 2. 作用域安全的构造函数
  3. 3. 惰性载入函数
  4. 4. 防篡改对象
  5. 5. JSON.stringify 和 JSON.parse

最近在练习JavaScript题目时发现有些实现自己立即并不能想出来,而且有些常见的方法的用法理解是有错误的如parseInt,所以记录一下。这是第四篇,定要温故而知新 。^_^

安全的类型检测

最安全的方法

1
2
3
isType(param,type){
return Object.prototype.toString.call(param) === '[object '+type+']'
}

也可以用这种方法来检测是否是原生的JSON

1
isNativeJSON = window.JSON && Object.prototype.toString.call(JSON) === '[object JSON]'

作用域安全的构造函数

当使用构造函数创建实例时若是没有使用new关键字,则会使得this指向window对象,会意外给window 对象增改属性。
改进: 增加this的类型检测

1
2
3
4
5
6
7
8
function Person(name,age){
if(this instanceof Person){
this.name = name
this.age = age
}else{
return new Person(name,age)
}
}

但是这种情况在只使用构造函数进行继承时会出现错误。 如以下的例子:

1
2
3
4
5
6
7
8
9
10
11
12
function Person(name,age){
if(this instanceof Person){
this.name = name
this.age = age
}else{
return new Person(name,age)
}
}
function Student(sex,name,age){
Person.apply(this,name,age)
this.sex = sex
}

这时如果使用Student去创建实例,则会只有sex 属性和一个person的实例

改进二: 使用继承来解决上述问题

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(name,age){
if(this instanceof Person){
this.name = name
this.age = age
}else{
return new Person(name,age)
}
}
function Student(sex,name,age){
Person.apply(this,name,age)
this.sex = sex
}
Student.prototype = new Person()

惰性载入函数

惰性载入即当有一个方法中有多个if 时并且只是进行一些检测之后就只执行其中的一个分支的情况。这种最常见的就是浏览器的类型检测如 在创建XMLHttpRequest 对象时。对于这种经检测只执行其中的一个分支的情况,有两种优化方式:

方法一: 在函数在第一次调用的过程中,该函数会被覆盖为另外一个按合适方式运行的函数。如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function createXHR() {
if (typeof XMLHttpRequest !== 'undefined') {
createXHR = function () {
return new XMLHttpRequest()
}
} else if (typeof ActiveObject !== 'undefined') {
createXHR = function () {
return new ActiveObject('Microsoft.XMLHTTP');
}
} else {
throw new Error('NO XHR object Available')
}
return createXHR() // important
}

方法二: 使用IIFE — 在声明函数时就指定适当的函数。这种情况下第一次调用函数不会损失性能,而在代码首次加载时会损失一点性能

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var createXHR = (function () {
if (typeof XMLHttpRequest !== 'undefined') {
return function () {
return new XMLHttpRequest()
}
} else if (typeof ActiveObject !== 'undefined') {
return function () {
return new ActiveObject('Microsoft.XMLHTTP');
}
} else {
return function () {
throw new Error('No XHR Object available')
}
}
})()

防篡改对象

定义防篡改对象是为了防止代码无意被修改,但是需注意的是 一旦把对象定义为防篡改,就无法撤销了。
首先是关于对象的属性的属性描述符。对于对象的属性 可以使用Object.defineProperty(对象名,属性名)获取到,共有 value、writable、enumerable和configurable四种属性值。只有configurable是true时,才可以使用defineProperty()来修改属性描述符,并且configurable修改成false是单向的,不能修改回去。

设置防篡改对象可以使用下面四种方法:
方法一:使用 writable:false configurable:false 来创建 不可修改、不可重定义、不可删除的 常量属性

方法二:使用Object.preventExtensions(对象名)来禁止一个对象添加新属性

方法三:使用Object.seal(对象名)来密封一个对象。即在一个对象上调用Object.preventExtensions()并把所有的属性标记为 configurable: false ,但是可以更改属性值

方法四:使用Object.freeze(对象名)会冻结一个对象。 就是在Object.seal() 并把所有”数据访问”属性标记为writable: false
这个方法是可以应用在对象的级别的最高的不可变性,但也只是会禁止对象本身及其任意直接属性的修改

JSON.stringify 和 JSON.parse

JSON.stringify(value[,replacer[,space]])

对于replacer可以是函数,也可以是一个数组。如果第二个参数是一个函数,那么序列化过程中的每个属性都会被这个函数转化和处理

如果第二个参数是一个数组,那么只有包含在这个数组中的属性才会被序列化到最终的JSON字符串中

如果第二个参数是null,那作用上和空着没啥区别,但是不想设置第二个参数,只是想设置第三个参数的时候,就可以设置第二个参数为null

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var friend={
"firstName": "Good",
"lastName": "Man",
"phone":"1234567",
"age":18
};
var friendAfter=JSON.stringify(friend,function(key,value){
if(key==="phone")
return "(000)"+value;
else if(typeof value === "number")
return value + 10;
else
return value; //如果你把这个else分句删除,那么结果会是undefined
});
console.log(friendAfter);
//输出:{"firstName":"Good","lastName":"Man","phone":"(000)1234567","age":28}

JSON.stringify() 在序列化过程中会依据一些规则进行优化,会产生一些”意外”的情况,需要注意。

文章目录
  1. 1. 安全的类型检测
  2. 2. 作用域安全的构造函数
  3. 3. 惰性载入函数
  4. 4. 防篡改对象
  5. 5. JSON.stringify 和 JSON.parse