总结
一、返回自身属性的方法:
Object.getOwnPropertyNames和Object.keys
Object.getOwnPropertyNames方法返回一个数组,成员是参数对象自身的全部属性的属性名,不管该属性是否可遍历。
Object.keys只返回对象自身的可遍历属性的全部属性名。
Object.keys([]) // []
Object.getOwnPorpertyNames([]) // ['length']
Object.keys(Object.protype) // []
Object.getOwnPorpertyNames(Object.prototype)
// ['hasownProperty',
// 'valueOf',
// 'constructor',
// 'toLocaleString'
// 'isPrototypeOf'
// 'propertyIsEnumerable'
// 'toString'
//]
二、描述对象
Object.defineProperty(),Obejct.defineProperties()
Object.defineProperty()方法允许通过属性描述对象,定义或修改一个属性,然后返回修改后的对象,它的用法如下。
Object.definedProperty(Object,propertyName,attributesObject)
三个属性分别代表:
object:属性所在对象
propertyName:字符串、属性名
attributesObject:属性描述对象
var obj = Object.definedProperty({},'p'{
value:123,
writable:false,
enumerable:true,
configurable:false // 不能重新定义描述对象
});
obj.p // 123
obj.p = 234;
obj.p // 123
注意:一旦定义了取值函数get或者存值函数set 就不能将writable属性设置为true 或者同时定义value属性 否则会报错:以下代码是错误的
var obj = {};
Object.defineProperty(obj,'p',{
value:123,
get:function(){
return 456;
}
})
// TypeError:Invalid property.
// A property cannot both have accessors and be writable or have a value
Object.defineProperty(obj,'p',{
writable:true,
get:function(){
return 456;
}
})
// TypeError:Invalid property descriptor.
// Cannot both specify accessors and value or writable attribute
三、判断对象某个属性是否可以遍历
Object.prototype.propertyIsEnumerable()
方法返回一个布尔值,用来判断某个属性是否可遍历。注意,这个方法只能用于判断对象自身的属性,对于继承的属性一律返回false
例如:
var obj = {};
obj.p = 123;
obj.propotype.propertyIsEnumerable('p') // true
obj.propotype.propertyIsEnumerable('toString') // false
四、存取器
var obj = Object.defineProperty({},'p',{
get:function(){
return 'grtter';
},
set:function(value){
console.log('setter:'+value);
}
这种写法实际上已经默认的将configurable和enumerable属性都为false
});
obj.p // "getter"
obj.p = 123 // "setter:123"
方法二:
var obj = {
get p(){
return 'getter';
},
set p(value){
console.log('setter:'+value);
}
这一种写法configurable和enumerable属性默认为true
}
存取器的小例子:
var obj = {
$n: 5,
get next(){ return this.$n++},
set next(){
if(n >= this.$n) this.$n = n;
else throw new Error('新的值必须大于当前值');
}
};
obj.next // 5
obj.next = 10;
obj.next // 10
obj.next = 5;
//Uncaught Error :新的值必须大于当前值
五、对象的拷贝
拷贝对象的所有属性
var extend = function (to,from){
for (var property in from){
to[property] = from[property];
}
return to;
}
extend({},{
a:1
})
缺点:如果遇到存取器定义的属性只会拷贝值
extend({},{
get a(){return 1}
})
// {a:1}
解决方法:Object.defineProperty
var extend = function(to,from){
for(var property in from){
if(!Object.defineProperty(property)) contiue;
Object.defineProperty(
to,
property,
Object.getOwnPropertyDescriptor(from,property)
);
}
return to;
}
上面代码中,hasOwnProperty那一行用来过滤掉继承的属性,否则可能会报错,因为Object.getOwnPropertyDescriptor读不到继承属性的属性描述对象
简单来说就是Object.getOwnPropertyDescriptor()搭配Object.defineProperty()使用,因为Object.getOwnPropertyDescriptor返回的是属性的描述对象,而Object.defineProperty()第三个属性缺的就是描述对象,随意在Object.defineProperty()中调用Object.getOwnPropertyDescriptor()方法;
六、控制对象状态
有时需要冻结对象的读写状态,防止对象被改变。JavaScript 提供了三种冻结方法,最弱的一种是Object.preventExtensions
,其次是Object.seal
,最强的是Object.freeze
。
1、Object.preventExtensions()
var obj = new Object();
Object.preventExtensions(obj);
Object.defineProperty(obj,'p',{
value : 'hello'
});
// TypeError: Cannot define property : p,object is not extensible
obj.p = 1;
obj.p // undefined
无法再添加新的属性
2、Object.isExtensible
// 用于检查一个对象是否使用Object.preventExtensions方法,也就是说,检查是否可以为一个对象添加属性
var obj = new Object();
Object.isExtensible(obj) // true
Object.preventExtensions(obj) ;
Object.isExtensible(obj) // false
2、Object.seal()
Object.seal方法既无法添加新属性 也无法删除旧属性
var obj = {p:'hello'};
Object.seal(obj);
delete object.p;
obj.p // "hello"
obj.x = 'world';
obj.x = // undefined
Object.seal实际上就是把属性的描述对象的configurable属性设置为false
var obj = {
p:'a'
};
//seal方法之前
Object.getOwnPropertyDescriptor(obj,'p')
// Object{
// value:'a',
// writable:true,
// enumerable:true,
// configurable:true
//}
Object.seal(obj);
//seal方法之后
Object.getOwnPropertyDescriptor(obj,'p');
// Object{
// value:'a',
// writable:true,
// enumerable:true,
// configurable:false
//}
Object.defineProperty(obj,'p',{
enumerable:false
})
//TypeError:cannot redefine property : p
小细节:
writable:如果为true,那么不管configurable是什么,都可通过obj.xxx = xxx来改变value
如果为false,configurable为true那么只能通过Object.defineProperty方法来改变value的值。
所以只要writable、configurable其中一个为true,就可以改变value的值只是方法不一样
因此这里如果writable是true,那么在seal后value的值是可以改变的。
同样:Object.isSealed() 用于检查一个对象是否使用了Object.seal方法
var obj = {p:'a'};
Object.seal(obj);
Object.isSealed(obj) // true
对于判断preventExtensions是否使用的Object.isExtensible()
Object.isExtensible(obj) // false
3、Obejct.freeze()
无法添加新属性、无法删除旧属性、无法改变属性的值,使得这个对象实际上变成了常量
var obj = {
p:'hello'
};
Object.freeze(obj);
obj.p = 'world';
obj.p // "hello"
obj.t = 'hello';
obj.t // undefined
delete obj.p // false
obj.p // "hello"
如果在严格模式下,则会报错
局限性
上面三个方法都有局限性 可以通过改变原型对象 来为对象增加属性
var obj = new Object();
Object.preventExtensions(obj);
var proro = Object.getPrototypeOf(obj);
proto.t = 'hello';
obj.t
// hello
解决办法:冻住原型
var obj = new Object();
Object.preventExtensions(obj);
var propo = Object.getPropotypeOf(obj);
Object.preventExtensions(obj);
proto.t = 'hello'
obj.t // undefined
另一个局限:
var obj = {
foo:1,
bar:['a','b']
};
Object.freeze(obj);
obj.bar.push('c');
obj.bar // ['a','b','c']
上面代码中,`obj.bar`属性指向一个数组,`obj`对象被冻结以后,这个指向无法改变,即无法指向其他值,但是所指向的数组是可以改变的。
七、数组
1、静态方法
Array.isArray 返回一个布尔值 可以弥补typeof的不足
var arr = [1,2,3];
typeof arr // "object"
Array.isArray(arr) // true
2、实例方法
1.valueOf()、toString()
valueOf是一个所有对象都有的方法 表示对该对象求值 不同的对象的valueOf方法不一致 数组的valueOf方法返回数组本身
var arr = [1,2,3];
arr.valueOf() // [1,2,3]
toString方法也是对象的通用方法 数组的toString方法返回字符串形式
var arr = [1, 2, 3];
arr.toString() // "1,2,3"
var arr = [1, 2, 3, [4, 5, 6]];
arr.toString() // "1,2,3,4,5,6"
2、push(),pop()
push方法在数组的末端添加一个或多个元素 返回数组的长度
var arr = [];
a.push(1);
a.push('a');
a.push(true);
a.push({});
arr // [1,'a',true,{}]
pop方法用于删除最后一个元素 并返回该元素
var arr =['a','b','c'];
arr.pop(arr); // 'c'
arr // ['a','b']
对于空数组pop方法 不会报错 而是返回undefined
push与pop结合使用,就构成了先进先出的栈结构
3、shift(),unshift()
shift()方法用于删除数组的第一个元素 并返回该元素 会改变元素
var a = ['a','b','c'];
a.shift() // 'a'
a // ['b','c']
shift()方法可以遍历清空一个数组
var list = [1,2,3,4];
var item;
while(item = list.shift()){
console.log(item);
}
list // []
unshift()方法用于在第一个位置添加元素 并返回添加元素后的数组的长度 会改变原数组
var a =['a','b','c'];
a.unshift('x'); // 4
a // ['x','a','b','c']
可以接受多个参数 unshift()
var arr = ['c','d']
arr.unshift('a','b') // 4
arr // ['a','b','c','d']
4、join()
join方法以指定参数作为分隔符 返回一个字符串 如果不提供参数 默认用逗号分隔
var a = [1,2,3,4];
a.join(' ') // '1 2 3 4'
a.join(' | ') // "1 | 2 | 3 | 4"
a.join() // "1,2,3,4"
如果数组成员是undefined或null或空位 会被转换为空字符串
[undefined,null].join('#')
//'#'
['a',,'b'].join('-');
//'a--b'
可以通过call方法 用于字符串或类似数组的对象
Array.prototype.join.call('hello','-')
// "h-e-l-l-o"
var obj = {0:'a',1:'b',length:2};
Array.prototype.join.call(obj,'-')
//'a-b'
5、concat()
concat 方法用于多个数组的合并 它将新数组的成员 添加到原数组成员的后部 然后返回一个新数组 原数组不变
['hello'].concat(['world'])
// ["hello","world"]
['hello'].concat(['world'],['!']);
// ["hello","world","!"]
[].concat({a:1},{b:2})
// [{a:1},{b:2}]
[2].concat({a:1})
// [2,{a:1}]
除了数组也可接受其他的值作为参数 添加到目标数组的尾部
[1,2,3].concat(4,5,6)
// [1,2,3,4,5,6]
如果数组成员包括对象,concat
方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用。
var obj = {a:1};
var oldArray = [obj];
var newArray = oldArray.concat();
obj.a = 2;
newArray[0].a // 2
当原数组改变时 新数组也会跟着改变
6、reverse()
颠倒排列数组 会改变原数组
var a = ['a','b','c'];
a.reserve() // ["c","b","a"]
a // ["a","b","c"]
7、slice()
提取目标数组的一部分 返回一个新数组
arr.slice(start,end);
var a = ['a', 'b', 'c'];
a.slice(0) // ["a", "b", "c"]
a.slice(1) // ["b", "c"]
a.slice(1, 2) // ["b"]
a.slice(2, 6) // ["c"]
a.slice() // ["a", "b", "c"]
没有参数实际上返回原数组的拷贝
如果为负数 则表示倒数计算的位置
var a = ['a','b','c'];
a.slice(-2); // ["b","c"]
a.slice(-2,-1) //["b"]
如果第一个参数大于数组的长度或者第二参数小于第一个参数则返回空数组
var a = ['a','b','c'];
a.slice(4) // []
a.slice(2,1) // []
slice方法的重要应用是将类似数组的对象转为真正的数组
Array.prototype.slice.call({0:'a',1:'b',length:2})
//['a','b']
Array.prototype.slice.call(document.qurrySelectorAll("div"));
Arrar.prototype.slice.call(arguments);
8、splice()
splice() 删除原数组的一部分成员 并再删除的位置添加一些新的数组成员 返回值是删除的元素
arr.splice(start,count,addElement1,addElement2,...)
var a = ['a','b','c','d','e','f'];
a.splice(4,2) // ["e","f"]
a // ["a","b","c","d"]
a.splice(4,2,2,1);
上面表示在把d后面元素删除并添加新的元素2,1
负数表示倒数的位置
如果第二个参数为0或者负数,则只会在该位置单纯的插入元素
如果只提供一个参数,等同于将原数组在指定位置拆分成两个数组
9、sort()
对数组成员进行排序 默认是按照字典顺序排序 原数组改变
['d','c','b','a'].sort()
// ['a','b','c','d']
[4,3,2,1].sort()
// [1,2,3,4]
[11,101].sort()
//[101,11]
[10111,1101,111].sort()
// [10111,1101,111]sort()方法不是按照大小排序,而是按照字典顺序。也就是说,数值会被先转成字符串,再按照字典顺序进行比较
sort的参数函数本身接受两个参数 表示进行比较的两个数组成员 如果该函数的返回值大于0,表示第一个成员排在第二个成员后面;其他情况下,都是第一个元素排在第二个元素前面
[10111,1101,111].sort(function(a,b){
return a-b;
})
//[111,1101,11101]
[
{ name: "张三", age: 30 },
{ name: "李四", age: 24 },
{ name: "王五", age: 28 }
].sort(function (o1, o2) {
return o1.age - o2.age;
})
// [
// { name: "李四", age: 24 },
// { name: "王五", age: 28 },
// { name: "张三", age: 30 }
// ]
// bad
[1, 4, 2, 6, 0, 6, 2, 6].sort((a, b) => a > b)
// good
[1, 4, 2, 6, 0, 6, 2, 6].sort((a, b) => a - b)
上面代码中,前一种排序算法返回的是布尔值,这是不推荐使用的。后一种是数值,才是更好的写法。
10、map()
将数组的元素传入map的参数函数的参数
var numbers = [1,2,3];
numbers.map(function (n){
return n + 1;
}) // [2,3,4]
numbers //[1,2,3]
var arr = ['a', 'b', 'c'];
第二个参数明说就是this的指向
[1, 2].map(function (e) {
return this[e];
}, arr)
// ['b', 'c']
如果数组有空位,map方法的回调函数在这个位置不会执行,会跳过数组的空位。
var f = function (n) { return 'a' };
[1, undefined, 2].map(f) // ["a", "a", "a"]
[1, null, 2].map(f) // ["a", "a", "a"]
[1, , 2].map(f) // ["a", , "a"]
上面代码中,map方法不会跳过undefined和null,但是会跳过空位。
11、forEach()
forEach()与map()方法很相似,接受三个参数 当前值 当前位置 整个数组
function log(element,index,array){
console.log('['+index+']='+element);
}
[2,5,9].forEach(log);
//[0] = 2;
//[1] = 5;
//[2] = 9;
forEach遍历数组不是为了得到返回值,而是为了在屏幕输出内容,所以不必使用map方法。
forEach方法也可以接受第二个参数,绑定参数函数的this变量。
var out = [];
[1, 2, 3].forEach(function(elem) {
this.push(elem * elem);
}, out);
out // [1, 4, 9]
注意forEach是无法打断执行 总是将所有的成员遍历完 想要在某个条件下中断循环 使用for循环
var arr = [1,2,3]
for(var i = 0;i < arr.length;i++){
if(arr[i] === 2) break;
console.log(arr[i]);
}
// 1
上面代码中,执行到数组的第二个成员时,就会中断执行。forEach方法做不到这一点。
forEach方法也会跳过数组的空位。
var log = function (n) {
console.log(n + 1);
};
[1, undefined, 2].forEach(log)
// 2
// NaN
// 3
[1, null, 2].forEach(log)
// 2
// 1
// 3
[1, , 2].forEach(log)
// 2
// 3
12、filter()
过滤数组成员 满足条件的成员组成一个新数组返回
参数是一个函数 数组的成员会依次执行此函数 返回结果为true的成员组成一个新数组返回 不会改变原数组
[1,2,3,4,5].filter(function(elem)){
return (elem > 3);
}
//[4,5]
filter可以接受三个参数 当前值 当前元素 数组
var a = [];
function f(elem,index,arr) {
return (index%2==0);
}
a=[1,2,3,4,5].filter(f);
console.log(a);
可以接受第二个参数 绑定函数内部的this
var obj ={max:3};
var myfliter = function (item) {
if (item >this.max) return true;
}
var a = [1,2,3,4,5].filter(myfliter,obj);
console.log(a);
13、some()、every()
some方法是只要一个成员的返回值是true,则整个some方法的返回值就是true,否则返回false。
var arr = [1,2,3,4,5,6]
arr.some(function(n){
return n > 3
});
//true
arr.every(function(){
return n > 3
})
//false
注意,对于空数组,some方法返回false,every方法返回true,回调函数都不会执行。
function isEven(x) { return x % 2 === 0 }
[].some(isEven) // false
[].every(isEven) // true
some和every方法还可以接受第二个参数,用来绑定参数函数内部的this变量。
八、包装对象
1.什么是包装对象?
var v1 = new Number(123);
var v2 = new String('abc');
var v3 = new Boolean(true);
typeof v1 // "object"
typeof v2 // "object"
typeof v3 // "object"
v1 === 123 // false
v2 === 'abc' // false
v3 === true // false
如果没有new单纯的用作普通函数
Number('123') // 123
String(123); // "123"
Boolean(123) // true
转化成对应类型的值
2.实例方法
1、valueOf
返回包装对象实例对应的原始类型的值
new Number(123).valueOf() // 123
new String('abc').valueOf() // "abc"
new Boolean(true).valueOf() // true
2、toString
toString()方法返回对应的字符串形式。
new Number(123).toString() // "123"
new String('abc').toString() // "abc"
new Boolean(true).toString() // "true"
3、原始类型与实例对象的自动转换
var str = 'abc'
str.length // 3
// 等同于
var strobj = new String(str)
String{
0:"a",1:"b",2:"c",length:3,
[[PrimitiveValue]]:"abc"
}
strobj.length // 3
自动转换生成的包装对象是只读的 无法修改 所以 字符串无法添加新属性
var s = 'Hello World';
s.x = 123;
s.x // undefined
4、自定义方法
在原型对象的String.prototype上定义
String.prototype.double = function(){
return this.valueOf() + this.valueOf();
};
'abc'.double // abcabc
Number.prototype.double = function(){
return this.valueOf() + this.valueOf();
};
(123).double() // 246
上面代码在String和Number这两个对象的原型上面,分别自定义了一个方法,从而可以在所有实例对象上调用。注意,最后一行的123外面必须要加上圆括号,否则后面的点运算符(.)会被解释成小数点。
九、Boolean对象
三大包装对象之一
var b = new Boolean(true);
typeof b // "object"
b.valueOf() // true
注意:false对应的包装对象实例,布尔运算的结果也是true
if(new Boolean(false)){
console.log('true');
} // true
if(new Boolean(false).valueOf()){
console.log('true');
} // 无输出
上面代码的第一个例子之所以得到true,是因为false对应的包装对象实例是一个对象,进行逻辑运算时,被自动转化成布尔值true(因为所有对象对应的布尔值都是true)。而实例的valueOf方法,则返回实例对应的原始值,本例为false。
Boolean函数的转换类型的作用
Boolean对象除了可以作为构造函数,还可以单独使用,将任意值转为布尔值。这时Boolean就是一个单纯的工具方法。
Boolean(undefined) // false
Boolean(null) // false
Boolean(0) // false
Boolean('') // false
Boolean(NaN) // false
Boolean(1) // true
Boolean('false') // true
Boolean([]) // true
Boolean({}) // true
Boolean(function () {}) // true
Boolean(/foo/) // true
顺便提一下,使用双重的否运算符(!)也可以将任意值转为对应的布尔值。
!!undefined // false
!!null // false
!!0 // false
!!'' // false
!!NaN // false
!!1 // true
!!'false' // true
!![] // true
!!{} // true
!!function(){} // true
!!/foo/ // true
最后,对于一些特殊值,Boolean对象前面加不加new,会得到完全相反的结果,必须小心。
if (Boolean(false)) {
console.log('true');
} // 无输出
if (new Boolean(false)) {
console.log('true');
} // true
if (Boolean(null)) {
console.log('true');
} // 无输出
if (new Boolean(null)) {
console.log('true');
} // true
十、Number对象
1、静态属性
Number对象拥有以下一些静态属性(即直接定义在Number对象上的属性,而不是定义在实例上的属性)。
Number.POSITIVE_INFINITY:正的无限,指向Infinity。
Number.NEGATIVE_INFINITY:负的无限,指向-Infinity。
Number.NaN:表示非数值,指向NaN。
Number.MIN_VALUE:表示最小的正数(即最接近0的正数,在64位浮点数体系中为5e-324),相应的,最接近0的负数为-Number.MIN_VALUE。
Number.MAX_SAFE_INTEGER:表示能够精确表示的最大整数,即9007199254740991。
Number.MIN_SAFE_INTEGER:表示能够精确表示的最小整数,即-9007199254740991。
Number.POSITIVE_INFINITY // Infinity
Number.NEGATIVE_INFINITY // -Infinity
Number.NaN // NaN
Number.MAX_VALUE
// 1.7976931348623157e+308
Number.MAX_VALUE < Infinity
// true
Number.MIN_VALUE
// 5e-324
Number.MIN_VALUE > 0
// true
Number.MAX_SAFE_INTEGER // 9007199254740991
Number.MIN_SAFE_INTEGER // -9007199254740991
3、实例方法
1、Number.prototype.toString()
(10).toString() // "10"
toString()还可以接受一个参数 表示输出的进制 如果省略这个参数 默认将数值先转为十进制 在输出字符串 否则 就根据参数指定的进制 将一个数字转化成某个进制的字符串
(10).toString(2) // "1010"
(10).toString(8) // "12"
(10).toString(16) // "a"
注意小数点:10写在括号里 JavaScript引擎会解释成小数点从而报错
10.toString(2)
// SystaxError: Unexepected token ILLEGAL
只要能够让JavaScript引擎不混淆小数点和对象的点运算符各种写法都能用除了为10加上括号 还可以在10后面加两个点 JavaScript会把第一个点理解成小数点(即10.0),把第二个小数点理解成调用对象属性,从而得到正确结果
10..toString(2);
// "1010"
// 其他的方法还包括
10 .toString(2) // "1010"
10.0.toString(2) // "1010"
也就意味着 可以直接对一个小数使用toString方法
10.5.toString() // "10.5"
10.5.toString(2) // "1010.1"
10.5.toString(8) // "12.4"
10.5.toString(16) // "a.8"
通过方括号也可以调用toString方法
10['toString'](2) // "1010"
toString方法只能将十进制的数,转为其他进制的字符串。如果要将其他进制的数,转回十进制,需要使用parseInt方法。
2、Number.prototype.toFixed()
toFixed方法现将一个数转为指定位数的小数,然后返回这个小数对应的字符串
(10).toFixed(2) // "10.00"
10.005.toFixed(2) // "10.01"
toFixed()方法的参数为小数位数,有效范围为0到100,超出这个范围将抛出 RangeError 错误
由于浮点数的原因,小数5的四舍五入是不确定的,使用的时候必须小心。
(10.055).toFixed(2) // 10.05
(10.005).toFixed(2) // 10.01
3、Number.prototype.toExponential()
toExponential方法是将一个数转为科学计数法形式
(10).toExponential() // '1e+1'
(1o).toExponrntial(1) // "1.0e+1"
(10).toExponential(2) // "1.00e+1"
(1234).toExponential() // "1.23E+3"
(1234).toExponential(1) // "1.2E+3"
(1234).toExponential(2) // "1.23E+3"
toExponential方法的参数是小数点后有效数字的位数,范围为0到100,超出这个范围,会抛出一个 RangeError 错误。
4、Number.prototype.toPrecision()
Number.prototype.toPrecision() 方法用于将一个数转为指定位数的有效数字
(12.34).toPrecision(1) // "1e+1"
(12.34).toPrecision(2) // "12"
(12.34).toPrecision(3) // "12.3"
(12.34).toPrecision(4) // "12.34"
该方法的参数为有效数字的位数,范围是1到100,超出这个范围会抛出 RangeError 错误。
该方法用于四舍五入时不太可靠,跟浮点数不是精确储存有关。
(12.35).toPrecision(3) // "12.3"
(12.25).toPrecision(3) // "12.3"
(12.15).toPrecision(3) // "12.2"
(12.45).toPrecision(3) // "12.4"
5、Number.prototype.toLocaleString()
Number.prototype.toLocaleString() 方法接受一个地区码作为参数
(123).toLocaleString('zh-Hans-CN-u-nu-hanidec')
// "一二三"
如果style属性的值为currency 则可以搭配currency属性 输出指定格式的货币字符串形式
(123).toLocaleString('zh-Hans-CN', { style: 'currency', currency: 'CNY' })
// "¥123.00"
(123).toLocaleString('de-DE', { style: 'currency', currency: 'EUR' })
// "123,00 €"
(123).toLocaleString('en-US', { style: 'currency', currency: 'USD' })
// "$123.00"
如果Number.prototype.toLocaleString()省略了参数,则由浏览器自行决定如何处理,通常会使用操作系统的地区设定。注意,该方法如果使用浏览器不认识的地区码,会抛出一个错误。
(123).toLocaleString('123') // 出错
4、自定义方法
与其他对象一样 Number.prototype对象上面可以自定义方法 被Number的实例继承
Number.prototype.add = function(x){
return this.x;
}
8['add'](2) // 10
上面代码为Number对象实例定义了一个add方法 在数值上调用某个方法 数值会自动转为Number的实例对象 所以就调用了add方法 由于add方法返回的还是数值 所以可以链式运算
Number.prototype.subtract = function(x){
return this - x;
};
(8).add(2).subtract(4)
//6
上面代码在Number对象的实例上部署了subtract方法,它可以与add方法链式调用。
我们还可以部署更复杂的方法。
Number.prototype.iterate = function () {
var result = [];
for (var i = 0; i <= this; i++) {
result.push(i);
}
return result;
};
(8).iterate()
// [0, 1, 2, 3, 4, 5, 6, 7, 8]
十一、String对象
1三个包装对象之一 用来生成字符串
var s1 = 'abc';
var s2 = new String('abc');
typeof s1 // "string"
typeof s2 // "object"
s2.valueOf() // "abc"
字符串对象是一个类似数组的对象(很像数组 但不是数组)
new String ('abc')
// String {0:"a",1:"b",2:"c",length:3}
(new String('abc'))[1] // "b"
上面代码中,字符串abc对应的字符串对象,有数值键(0、1、2)和length属性,所以可以像数组那样取值。
除了用作构造函数,String对象还可以当作工具
方法使用,将任意类型的值转为字符串。
String(true) // "true"
String(5) // "5"
2、静态方法
1、String.fromCharCode()
该方法的参数是一个或多个数值,代表 Unicode 码点,返回值是这些码点组成的字符串。
String.from
十二、JSON对象
1.JSON.stringify()
JSON.stringify()
JSON.stringify()方法用于将一个值转为 JSON 字符串。该字符串符合 JSON 格式,并且可以被JSON.parse()方法还原。
JSON.stringify 会忽略对象的不可遍历的属性
var obj = {};
Object.defineProperties(obj,{
'foo':{
value:1,
enumerable:true
},
'bar':{
value:2,
enumerable:false
}
});
JSON.stringify(obj); // "{"foo":1}"
JSON.stringify()还可以接受第二个参数 一个数组
指定那些参数需要转换成字符串
var obj = {
'prop1': 'value1',
'prop2': 'value2',
'prop3': 'value3'
};
var selectedProperties = ['prop1', 'prop2'];
JSON.stringify(obj, selectedProperties)
// "{"prop1":"value1","prop2":"value2"}"
第二个参数还可以是一个函数 用来更改JSON.stringify()的返回值
function f(key, value) {
if (typeof value === "number") {
value = 2 * value;
}
return value;
}
JSON.stringify({ a: 1, b: 2 }, f)
// '{"a": 2,"b": 4}'
JSON.stringfy()是依次向下递归的 第一次是整体 也就是返回的结果是 空键值 对象本身 第二次才是对象包含的内容
var obj = {a: {b: 1}};
function f(key, value) {
console.log("["+ key +"]:" + value);
return value;
}
JSON.stringify(obj, f)
// []:[object Object]
// [a]:[object Object]
// [b]:1
// '{"a":{"b":1}}'
上面代码中,对象obj一共会被f函数处理三次,输出的最后那行是JSON.stringify()的默认输出。第一次键名为空,键值是整个对象obj;第二次键名为a,键值是{b: 1};第三次键名为b,键值为1。
JSON.stringify()还可以接受第三个参数,用于增加返回的 JSON 字符串的可读性。比如换行 以及制表符
// 默认输出
JSON.stringify({ p1: 1, p2: 2 })
// JSON.stringify({ p1: 1, p2: 2 })
// 分行输出
JSON.stringify({ p1: 1, p2: 2 }, null, '\t')
// {
// "p1": 1,
// "p2": 2
// }
2.toJSON()
如果对象本身有toJSON方法 那么就相当于JSON.stringify的参数对象忽略掉其他属性 只看toJSON方法中的属性 例:
var user = {
firstName: '三',
lastName: '张',
get fullName(){
return this.lastName + this.firstName;
},
toJSON: function () {
return {
name: this.lastName + this.firstName
};
}
};
JSON.stringify(user)
// "{"name":"张三"}"
常用方法 就是正则对象转为字符串:因为JSON.stringify方法默认不能转换正则对象 但是设置toJSON方法后 就可以转换正则对象了
var obj = {
reg: /foo/
};
// 不设置 toJSON 方法时
JSON.stringify(obj) // "{"reg":{}}"
// 设置 toJSON 方法时
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/) // ""/foo/""
3.JSON.parse()
将JSON字符串转换为对应的值 JSON.stringify方法的逆用
JSON.parse('{})') // {}
JSON.parse('true') // true
var o = JSON.parse('{"name":"张三"}')
o.name // 张三
bject Object]
// [b]:1
// ‘{“a”:{“b”:1}}’
上面代码中,对象obj一共会被f函数处理三次,输出的最后那行是JSON.stringify()的默认输出。第一次键名为空,键值是整个对象obj;第二次键名为a,键值是{b: 1};第三次键名为b,键值为1。
JSON.stringify()还可以接受第三个参数,用于增加返回的 JSON 字符串的可读性。比如换行 以及制表符
// 默认输出
JSON.stringify({ p1: 1, p2: 2 })
// JSON.stringify({ p1: 1, p2: 2 })
// 分行输出
JSON.stringify({ p1: 1, p2: 2 }, null, ‘\t’)
// {
// “p1”: 1,
// “p2”: 2
// }
### 2.toJSON()
如果对象本身有toJSON方法 那么就相当于JSON.stringify的参数对象忽略掉其他属性 只看toJSON方法中的属性 例:
var user = {
firstName: ‘三’,
lastName: ‘张’,
get fullName(){
return this.lastName + this.firstName;
},
toJSON: function () {
return {
name: this.lastName + this.firstName
};
}
};
JSON.stringify(user)
// “{“name”:“张三”}”
常用方法 就是正则对象转为字符串:因为JSON.stringify方法默认不能转换正则对象 但是设置toJSON方法后 就可以转换正则对象了
var obj = {
reg: /foo/
};
// 不设置 toJSON 方法时
JSON.stringify(obj) // “{“reg”:{}}”
// 设置 toJSON 方法时
RegExp.prototype.toJSON = RegExp.prototype.toString;
JSON.stringify(/foo/) // “”/foo/""
### 3.JSON.parse()
将JSON字符串转换为对应的值 JSON.stringify方法的逆用
JSON.parse(’{})’) // {}
JSON.parse(‘true’) // true
var o = JSON.parse(’{“name”:“张三”}’)
o.name // 张三