阮一峰老师的javascript标准参考教程:object对象和object方法(代码片段)

moumoon moumoon     2022-12-17     446

关键词:

Object对象

1. 概述

1.1 生成方法

对象(object)是 JavaScript 语言的核心概念,也是最重要的数据类型。

什么是对象?简单说,对象就是一组“键值对”(key-value)的集合,是一种无序的复合数据集合。

var obj = 
  foo: ‘Hello‘,
  bar: ‘World‘
;

上面代码中,大括号就定义了一个对象,它被赋值给变量obj,所以变量obj就指向一个对象。该对象内部包含两个键值对(又称为两个“成员”),第一个键值对是foo: ‘Hello‘,其中foo是“键名”(成员的名称),字符串Hello是“键值”(成员的值)。键名与键值之间用冒号分隔。第二个键值对是bar: ‘World‘bar是键名,World是键值。两个键值对之间用逗号分隔。

1.2 键名

对象的所有键名都是字符串(ES6 又引入了 Symbol 值也可以作为键名),所以加不加引号都可以。上面的代码也可以写成下面这样。

var obj = 
  ‘foo‘: ‘Hello‘,
  ‘bar‘: ‘World‘
;

如果键名是数值,会被自动转为字符串。

var obj = 
  1: ‘a‘,
  3.2: ‘b‘,
  1e2: true,
  1e-2: true,
  .234: true,
  0xFF: true
;

obj
// Object 
//   1: "a",
//   3.2: "b",
//   100: true,
//   0.01: true,
//   0.234: true,
//   255: true
// 

obj[‘100‘] // true

上面代码中,对象obj的所有键名虽然看上去像数值,实际上都被自动转成了字符串。

如果键名不符合标识名的条件(比如第一个字符为数字,或者含有空格或运算符),且也不是数字,则必须加上引号,否则会报错。

// 报错
var obj = 
  1p: ‘Hello World‘
;

// 不报错
var obj = 
  ‘1p‘: ‘Hello World‘,
  ‘h w‘: ‘Hello World‘,
  ‘p+q‘: ‘Hello World‘
;

上面对象的三个键名,都不符合标识名的条件,所以必须加上引号。

对象的每一个键名又称为“属性”(property),它的“键值”可以是任何数据类型。如果一个属性的值为函数,通常把这个属性称为“方法”,它可以像函数那样调用。

var obj = 
  p: function (x) 
    return 2 * x;
  
;

obj.p(1) // 2

上面代码中,对象obj的属性p,就指向一个函数。

如果属性的值还是一个对象,就形成了链式引用。

var o1 = ;
var o2 =  bar: ‘hello‘ ;

o1.foo = o2;
o1.foo.bar // "hello"

上面代码中,对象o1的属性foo指向对象o2,就可以链式引用o2的属性。

对象的属性之间用逗号分隔,最后一个属性后面可以加逗号(trailing comma),也可以不加。

var obj = 
  p: 123,
  m: function ()  ... ,

上面的代码中,m属性后面的那个逗号,有没有都可以。

属性可以动态创建,不必在对象声明时就指定。

var obj = ;
obj.foo = 123;
obj.foo // 123

上面代码中,直接对obj对象的foo属性赋值,结果就在运行时创建了foo属性。

1.3 对象的引用

如果不同的变量名指向同一个对象,那么它们都是这个对象的引用,也就是说指向同一个内存地址。修改其中一个变量,会影响到其他所有变量。

var o1 = ;
var o2 = o1;

o1.a = 1;
o2.a // 1

o2.b = 2;
o1.b // 2

上面代码中,o1o2指向同一个对象,因此为其中任何一个变量添加属性,另一个变量都可以读写该属性。

此时,如果取消某一个变量对于原对象的引用,不会影响到另一个变量。

var o1 = ;
var o2 = o1;

o1 = 1;
o2 // 

上面代码中,o1o2指向同一个对象,然后o1的值变为1,这时不会对o2产生影响,o2还是指向原来的那个对象。

但是,这种引用只局限于对象,如果两个变量指向同一个原始类型的值。那么,变量这时都是值的拷贝。

var x = 1;
var y = x;

x = 2;
y // 1

上面的代码中,当x的值发生变化后,y的值并不变,这就表示yx并不是指向同一个内存地址。

1.4 表达式还是语句?

对象采用大括号表示,这导致了一个问题:如果行首是一个大括号,它到底是表达式还是语句?

 foo: 123 

JavaScript 引擎读到上面这行代码,会发现可能有两种含义。第一种可能是,这是一个表达式,表示一个包含foo属性的对象;第二种可能是,这是一个语句,表示一个代码区块,里面有一个标签foo,指向表达式123

为了避免这种歧义,V8 引擎规定,如果行首是大括号,一律解释为对象。不过,为了避免歧义,最好还是在大括号前加上圆括号。

( foo: 123)

这种差异在eval语句(作用是对字符串求值)中反映得最明显。

eval(‘foo: 123‘) // 123
eval(‘(foo: 123)‘) // foo: 123

上面代码中,如果没有圆括号,eval将其理解为一个代码块;加上圆括号以后,就理解成一个对象。

2. 属性的操作

2.1 读取属性

读取对象的属性,有两种方法,一种是使用点运算符,还有一种是使用方括号运算符。

var obj = 
  p: ‘Hello World‘
;

obj.p // "Hello World"
obj[‘p‘] // "Hello World"

上面代码分别采用点运算符和方括号运算符,读取属性p

请注意,如果使用方括号运算符,键名必须放在引号里面,否则会被当作变量处理。

var foo = ‘bar‘;

var obj = 
  foo: 1,
  bar: 2
;

obj.foo  // 1
obj[foo]  // 2

上面代码中,引用对象objfoo属性时,如果使用点运算符,foo就是字符串;如果使用方括号运算符,但是不使用引号,那么foo就是一个变量,指向字符串bar

方括号运算符内部还可以使用表达式。

obj[‘hello‘ + ‘ world‘]
obj[3 + 3]

数字键可以不加引号,因为会自动转成字符串。

var obj = 
  0.7: ‘Hello World‘
;

obj[‘0.7‘] // "Hello World"
obj[0.7] // "Hello World"

上面代码中,对象obj的数字键0.7,加不加引号都可以,因为会被自动转为字符串。

注意,数值键名不能使用点运算符(因为会被当成小数点),只能使用方括号运算符。

var obj = 
  123: ‘hello world‘
;

obj.123 // 报错
obj[123] // "hello world"

上面代码的第一个表达式,对数值键名123使用点运算符,结果报错。第二个表达式使用方括号运算符,结果就是正确的。

2.2 属性的赋值

点运算符和方括号运算符,不仅可以用来读取值,还可以用来赋值。

var obj = ;

obj.foo = ‘Hello‘;
obj[‘bar‘] = ‘World‘;

上面代码中,分别使用点运算符和方括号运算符,对属性赋值。

JavaScript 允许属性的“后绑定”,也就是说,你可以在任意时刻新增属性,没必要在定义对象的时候,就定义好属性。

var obj =  p: 1 ;

// 等价于

var obj = ;
obj.p = 1;

2.3 查看所有属性

查看一个对象本身的所有属性,可以使用Object.keys方法。

var obj = 
  key1: 1,
  key2: 2
;

Object.keys(obj);
// [‘key1‘, ‘key2‘]

2.4 delete 命令

delete命令用于删除对象的属性,删除成功后返回true

var obj =  p: 1 ;
Object.keys(obj) // ["p"]

delete obj.p // true
obj.p // undefined
Object.keys(obj) // []

上面代码中,delete命令删除对象objp属性。删除后,再读取p属性就会返回undefined,而且Object.keys方法的返回值也不再包括该属性。

注意,删除一个不存在的属性,delete不报错,而且返回true

var obj = ;
delete obj.p // true

上面代码中,对象obj并没有p属性,但是delete命令照样返回true。因此,不能根据delete命令的结果,认定某个属性是存在的。

只有一种情况,delete命令会返回false,那就是该属性存在,且不得删除。

var obj = Object.defineProperty(, ‘p‘, 
  value: 123,
  configurable: false
);

obj.p // 123
delete obj.p // false

上面代码之中,对象objp属性是不能删除的,所以delete命令返回false(关于Object.defineProperty方法的介绍,请看《标准库》的 Object 对象一章)。

另外,需要注意的是,delete命令只能删除对象本身的属性,无法删除继承的属性(关于继承参见《面向对象编程》章节)。

var obj = ;
delete obj.toString // true
obj.toString // function toString()  [native code] 

上面代码中,toString是对象obj继承的属性,虽然delete命令返回true,但该属性并没有被删除,依然存在。这个例子还说明,即使delete返回true,该属性依然可能读取到值。

2.5 in 运算符

in运算符用于检查对象是否包含某个属性(注意,检查的是键名,不是键值),如果包含就返回true,否则返回false

var obj =  p: 1 ;
‘p‘ in obj // true

in运算符的一个问题是,它不能识别哪些属性是对象自身的,哪些属性是继承的。

var obj = ;
‘toString‘ in obj // true

上面代码中,toString方法不是对象obj自身的属性,而是继承的属性。但是,in运算符不能识别,对继承的属性也返回true

2.6 for…in 循环

for...in循环用来遍历一个对象的全部属性。

var obj = a: 1, b: 2, c: 3;

for (var i in obj) 
  console.log(obj[i]);

// 1
// 2
// 3

下面是一个使用for...in循环,提取对象属性名的例子。

var obj = 
  x: 1,
  y: 2
;
var props = [];
var i = 0;

for (var p in obj) 
  props[i++] = p


props // [‘x‘, ‘y‘]

for...in循环有两个使用注意点。

  • 它遍历的是对象所有可遍历(enumerable)的属性,会跳过不可遍历的属性。
  • 它不仅遍历对象自身的属性,还遍历继承的属性。

举例来说,对象都继承了toString属性,但是for...in循环不会遍历到这个属性。

var obj = ;
// toString 属性是存在的
obj.toString // toString()  [native code] 

for (var p in obj) 
  console.log(p);
 // 没有任何输出

上面代码中,对象obj继承了toString属性,该属性不会被for...in循环遍历到,因为它默认是“不可遍历”的。关于对象属性的可遍历性,参见《标准库》章节中 Object 一章的介绍。

如果继承的属性是可遍历的,那么就会被for...in循环遍历到。但是,一般情况下,都是只想遍历对象自身的属性,所以使用for...in的时候,应该结合使用hasOwnProperty方法,在循环内部判断一下,某个属性是否为对象自身的属性。

var person =  name: ‘老张‘ ;

for (var key in person) 
  if (person.hasOwnProperty(key)) 
    console.log(key);
  

// name

3. with 语句

with语句的格式如下:

with (对象) 
  语句;

它的作用是操作同一个对象的多个属性时,提供一些书写的方便。

// 例一
var obj = 
  p1: 1,
  p2: 2,
;
with (obj) 
  p1 = 4;
  p2 = 5;

// 等同于
obj.p1 = 4;
obj.p2 = 5;

// 例二
with (document.links[0])
  console.log(href);
  console.log(title);
  console.log(style);

// 等同于
console.log(document.links[0].href);
console.log(document.links[0].title);
console.log(document.links[0].style);

注意,如果with区块内部有变量的赋值操作,必须是当前对象已经存在的属性,否则会创造一个当前作用域的全局变量。

var obj = ;
with (obj) 
  p1 = 4;
  p2 = 5;


obj.p1 // undefined
p1 // 4

上面代码中,对象obj并没有p1属性,对p1赋值等于创造了一个全局变量p1。正确的写法应该是,先定义对象obj的属性p1,然后在with区块内操作它。

这是因为with区块没有改变作用域,它的内部依然是当前作用域。这造成了with语句的一个很大的弊病,就是绑定对象不明确。

with (obj) 
  console.log(x);

单纯从上面的代码块,根本无法判断x到底是全局变量,还是对象obj的一个属性。这非常不利于代码的除错和模块化,编译器也无法对这段代码进行优化,只能留到运行时判断,这就拖慢了运行速度。因此,建议不要使用with语句,可以考虑用一个临时变量代替with

with(obj1.obj2.obj3) 
  console.log(p1 + p2);


// 可以写成
var temp = obj1.obj2.obj3;
console.log(temp.p1 + temp.p2);

4. Object对象自身的方法(又称为”静态方法“)和Object对象实例方法

1. 概述

JavaScript 原生提供Object对象(注意起首的O是大写),本章介绍该对象原生的各种方法。

JavaScript 的所有其他对象都继承自Object对象,即那些对象都是Object的实例。

Object对象的原生方法分成两类:Object本身的方法与Object的实例方法。

(1)Object对象本身的方法

所谓”本身的方法“就是直接定义在Object对象的方法。

Object.print = function (o)  console.log(o) ;

上面代码中,print方法就是直接定义在Object对象上。

(2)Object的实例方法

所谓实例方法就是定义在Object原型对象Object.prototype上的方法。它可以被Object实例直接使用。

Object.prototype.print = function () 
  console.log(this);
;

var obj = new Object();
obj.print() // Object

上面代码中,Object.prototype定义了一个print方法,然后生成一个Object的实例objobj直接继承了Object.prototype的属性和方法,可以直接使用obj.print调用print方法。也就是说,obj对象的print方法实质上就是调用Object.prototype.print方法。

关于原型对象object.prototype的详细解释,参见《面向对象编程》章节。这里只要知道,凡是定义在Object.prototype对象上面的属性和方法,将被所有实例对象共享就可以了。

以下先介绍Object作为函数的用法,然后再介绍Object对象的原生方法,分成对象自身的方法(又称为”静态方法“)和实例方法两部分。

2. Object()

Object本身是一个函数,可以当作工具方法使用,将任意值转为对象。这个方法常用于保证某个值一定是对象。

如果参数为空(或者为undefinednull),Object()返回一个空对象。

var obj = Object();
// 等同于
var obj = Object(undefined);
var obj = Object(null);

obj instanceof Object // true

上面代码的含义,是将undefinednull转为对象,结果得到了一个空对象obj

instanceof运算符用来验证,一个对象是否为指定的构造函数的实例。obj instanceof Object返回true,就表示obj对象是Object的实例。

如果参数是原始类型的值,Object方法将其转为对应的包装对象的实例(参见《原始类型的包装对象》一章)。

var obj = Object(1);
obj instanceof Object // true
obj instanceof Number // true

var obj = Object(‘foo‘);
obj instanceof Object // true
obj instanceof String // true

var obj = Object(true);
obj instanceof Object // true
obj instanceof Boolean // true

上面代码中,Object函数的参数是各种原始类型的值,转换成对象就是原始类型值对应的包装对象。

如果Object方法的参数是一个对象,它总是返回该对象,即不用转换。

var arr = [];
var obj = Object(arr); // 返回原数组
obj === arr // true

var value = ;
var obj = Object(value) // 返回原对象
obj === value // true

var fn = function () ;
var obj = Object(fn); // 返回原函数
obj === fn // true

利用这一点,可以写一个判断变量是否为对象的函数。

function isObject(value) 
  return value === Object(value);


isObject([]) // true
isObject(true) // false

3. Object 构造函数

Object不仅可以当作工具函数使用,还可以当作构造函数使用,即前面可以使用new命令。

Object构造函数的首要用途,是直接通过它来生成新对象。

var obj = new Object();

注意,通过var obj = new Object()的写法生成新对象,与字面量的写法var obj = 是等价的。或者说,后者只是前者的一种简便写法。

Object构造函数的用法与工具方法很相似,几乎一模一样。使用时,可以接受一个参数,如果该参数是一个对象,则直接返回这个对象;如果是一个原始类型的值,则返回该值对应的包装对象(详见《包装对象》一章)。

var o1 = a: 1;
var o2 = new Object(o1);
o1 === o2 // true

var obj = new Object(123);
obj instanceof Number // true

虽然用法相似,但是Object(value)new Object(value)两者的语义是不同的,Object(value)表示将value转成一个对象,new Object(value)则表示新生成一个对象,它的值是value

4. Object 的静态方法

所谓“静态方法”,是指部署在Object对象自身的方法。

4.1 Object.keys(),Object.getOwnPropertyNames()

Object.keys方法和Object.getOwnPropertyNames方法都用来遍历对象的属性。

Object.keys方法的参数是一个对象,返回一个数组。该数组的成员都是该对象自身的(而不是继承的)所有属性名。

var obj = 
  p1: 123,
  p2: 456
;

Object.keys(obj) // ["p1", "p2"]

Object.getOwnPropertyNames方法与Object.keys类似,也是接受一个对象作为参数,返回一个数组,包含了该对象自身的所有属性名。

var obj = 
  p1: 123,
  p2: 456
;

Object.getOwnPropertyNames(obj) // ["p1", "p2"]

对于一般的对象来说,Object.keys()Object.getOwnPropertyNames()返回的结果是一样的。只有涉及不可枚举属性时,才会有不一样的结果。Object.keys方法只返回可枚举的属性(详见《对象属性的描述对象》一章),Object.getOwnPropertyNames方法还返回不可枚举的属性名。

var a = [‘Hello‘, ‘World‘];

Object.keys(a) // ["0", "1"]
Object.getOwnPropertyNames(a) // ["0", "1", "length"]

上面代码中,数组的length属性是不可枚举的属性,所以只出现在Object.getOwnPropertyNames方法的返回结果中。

由于 JavaScript 没有提供计算对象属性个数的方法,所以可以用这两个方法代替。

var obj = 
  p1: 123,
  p2: 456
;

Object.keys(obj).length // 2
Object.getOwnPropertyNames(obj).length // 2

一般情况下,几乎总是使用Object.keys方法,遍历数组的属性。

4.2 其他方法

除了上面提到的两个方法,Object还有不少其他静态方法,将在后文逐一详细介绍。

(1)对象属性模型的相关方法

  • Object.getOwnPropertyDescriptor():获取某个属性的描述对象。
  • Object.defineProperty():通过描述对象,定义某个属性。
  • Object.defineProperties():通过描述对象,定义多个属性。

(2)控制对象状态的方法

  • Object.preventExtensions():防止对象扩展。
  • Object.isExtensible():判断对象是否可扩展。
  • Object.seal():禁止对象配置。
  • Object.isSealed():判断一个对象是否可配置。
  • Object.freeze():冻结一个对象。
  • Object.isFrozen():判断一个对象是否被冻结。

(3)原型链相关方法

  • Object.create():该方法可以指定原型对象和属性,返回一个新的对象。
  • Object.getPrototypeOf():获取对象的Prototype对象。

5. Object 的实例方法

除了静态方法,还有不少方法定义在Object.prototype对象。它们称为实例方法,所有Object的实例对象都继承了这些方法。

Object实例对象的方法,主要有以下六个。

  • Object.prototype.valueOf():返回当前对象对应的值。
  • Object.prototype.toString():返回当前对象对应的字符串形式。
  • Object.prototype.toLocaleString():返回当前对象对应的本地字符串形式。
  • Object.prototype.hasOwnProperty():判断某个属性是否为当前对象自身的属性,还是继承自原型对象的属性。
  • Object.prototype.isPrototypeOf():判断当前对象是否为另一个对象的原型。
  • Object.prototype.propertyIsEnumerable():判断某个属性是否可枚举。

本节介绍前四个方法,另外两个方法将在后文相关章节介绍。

5.1 Object.prototype.valueOf()

valueOf方法的作用是返回一个对象的“值”,默认情况下返回对象本身。

var obj = new Object();
obj.valueOf() === obj // true

上面代码比较obj.valueOf()obj本身,两者是一样的。

valueOf方法的主要用途是,JavaScript 自动类型转换时会默认调用这个方法(详见《数据类型转换》一章)。

var obj = new Object();
1 + obj // "1[object Object]"

上面代码将对象obj与数字1相加,这时 JavaScript 就会默认调用valueOf()方法,求出obj的值再与1相加。所以,如果自定义valueOf方法,就可以得到想要的结果。

var obj = new Object();
obj.valueOf = function () 
  return 2;
;

1 + obj // 3

上面代码自定义了obj对象的valueOf方法,于是1 + obj就得到了3。这种方法就相当于用自定义的obj.valueOf,覆盖Object.prototype.valueOf

5.2 Object.prototype.toString()

toString方法的作用是返回一个对象的字符串形式,默认情况下返回类型字符串。

var o1 = new Object();
o1.toString() // "[object Object]"

var o2 = a:1;
o2.toString() // "[object Object]"

上面代码表示,对于一个对象调用toString方法,会返回字符串[object Object],该字符串说明对象的类型。

字符串[object Object]本身没有太大的用处,但是通过自定义toString方法,可以让对象在自动类型转换时,得到想要的字符串形式。

var obj = new Object();

obj.toString = function () 
  return ‘hello‘;
;

obj + ‘ ‘ + ‘world‘ // "hello world"

上面代码表示,当对象用于字符串加法时,会自动调用toString方法。由于自定义了toString方法,所以返回字符串hello world

数组、字符串、函数、Date 对象都分别部署了自定义的toString方法,覆盖了Object.prototype.toString方法。

[1, 2, 3].toString() // "1,2,3"

‘123‘.toString() // "123"

(function () 
  return 123;
).toString()
// "function () 
//   return 123;
// "

(new Date()).toString()
// "Tue May 10 2016 09:11:31 GMT+0800 (CST)"

上面代码中,数组、字符串、函数、Date 对象调用toString方法,并不会返回[object Object],因为它们都自定义了toString方法,覆盖原始方法。

5.3 toString() 的应用:判断数据类型

Object.prototype.toString方法返回对象的类型字符串,因此可以用来判断一个值的类型。

var obj = ;
obj.toString() // "[object Object]"

上面代码调用空对象的toString方法,结果返回一个字符串object Object,其中第二个Object表示该值的构造函数。这是一个十分有用的判断数据类型的方法。

由于实例对象可能会自定义toString方法,覆盖掉Object.prototype.toString方法,所以为了得到类型字符串,最好直接使用Object.prototype.toString方法。通过函数的call方法,可以在任意值上调用这个方法,帮助我们判断这个值的类型。

Object.prototype.toString.call(value)

上面代码表示对value这个值调用Object.prototype.toString方法。假如value..prototype.toString已经被覆盖也没有影响,因为call只是借助这个方法Object.prototype.toString。

不同数据类型的Object.prototype.toString方法返回值如下。

  • 数值:返回[object Number]
  • 字符串:返回[object String]
  • 布尔值:返回[object Boolean]
  • undefined:返回[object Undefined]
  • null:返回[object Null]
  • 数组:返回[object Array]
  • arguments 对象:返回[object Arguments]
  • 函数:返回[object Function]
  • Error 对象:返回[object Error]
  • Date 对象:返回[object Date]
  • RegExp 对象:返回[object RegExp]
  • 其他对象:返回[object Object]

这就是说,Object.prototype.toString可以看出一个值到底是什么类型。

Object.prototype.toString.call(2) // "[object Number]"
Object.prototype.toString.call(‘‘) // "[object String]"
Object.prototype.toString.call(true) // "[object Boolean]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(Math) // "[object Math]"
Object.prototype.toString.call() // "[object Object]"
Object.prototype.toString.call([]) // "[object Array]"

利用这个特性,可以写出一个比typeof运算符更准确的类型判断函数。

var type = function (o)
  var s = Object.prototype.toString.call(o);
  return s.match(/\[object (.*?)\]/)[1].toLowerCase();
;

type(); // "object"
type([]); // "array"
type(5); // "number"
type(null); // "null"
type(); // "undefined"
type(/abcd/); // "regex"
type(new Date()); // "date"

在上面这个type函数的基础上,还可以加上专门判断某种类型数据的方法。

var type = function (o)
  var s = Object.prototype.toString.call(o);
  return s.match(/\[object (.*?)\]/)[1].toLowerCase();
;

[‘Null‘,
 ‘Undefined‘,
 ‘Object‘,
 ‘Array‘,
 ‘String‘,
 ‘Number‘,
 ‘Boolean‘,
 ‘Function‘,
 ‘RegExp‘
].forEach(function (t) 
  type[‘is‘ + t] = function (o) 
    return type(o) === t.toLowerCase();
  ;
);

type.isObject() // true
type.isNumber(NaN) // true
type.isRegExp(/abc/) // true

5.4 Object.prototype.toLocaleString()

Object.prototype.toLocaleString方法与toString的返回结果相同,也是返回一个值的字符串形式。

var obj = ;
obj.toString(obj) // "[object Object]"
obj.toLocaleString(obj) // "[object Object]"

这个方法的主要作用是留出一个接口,让各种不同的对象实现自己版本的toLocaleString用来返回针对某些地域的特定的值。目前,主要有三个对象自定义了toLocaleString方法。

  • Array.prototype.toLocaleString()
  • Number.prototype.toLocaleString()
  • Date.prototype.toLocaleString()

举例来说,日期的实例对象的toStringtoLocaleString返回值就不一样,而且toLocaleString的返回值跟用户设定的所在地域相关。

var date = new Date();
date.toString() // "Tue Jan 01 2018 12:01:33 GMT+0800 (CST)"
date.toLocaleString() // "1/01/2018, 12:01:33 PM"

5.5 Object.prototype.hasOwnProperty()

Object.prototype.hasOwnProperty方法接受一个字符串作为参数,返回一个布尔值,表示该实例对象自身是否具有该属性。

var obj = 
  p: 123
;

obj.hasOwnProperty(‘p‘) // true
obj.hasOwnProperty(‘toString‘) // false

上面代码中,对象obj自身具有p属性,所以返回truetoString属性是继承的,所以返回false

 

阮一峰老师javascript课程学习笔记

...本轮循环,返回循环结构的头部,开始下一轮循环。3、JavaScript内部所有数字都是以64位浮点数形式存储,涉及小数的运算和比较需要特别小心。(-1)^符号位*1.xx...xx*2^指数位4、NaN是JavaScript的特殊值,表示“非数字(NotaNum 查看详情

阮一峰的介绍

...作的大神。IT领域,在前端开发中算是大神了。他写的书JavaScript标准参考教程、ECMAScript6入门,目前书在网络上已经开源,是目前前端学习的重要参考。他的网络日志http://www.ruanyifeng.com/ 查看详情

es6阮一峰阅读学习

...MAScript6入门 一、ECMAScript6简介1.什么是ECMAScript6? JavaScript语言的下一代标准。2015年6月发布,正式名称是《ECMAScript2015标准》。思考:编程语言和英语、法语语言差不多吧。其实就是语言的标准、规范之类,和英语语法差... 查看详情

阮一峰老师的es6入门:async函数(代码片段)

async函数1.含义ES2017标准引入了async函数,使得异步操作变得更加方便。async函数是什么?一句话,它就是Generator函数的语法糖。前文有一个Generator函数,依次读取两个文件。constfs=require(‘fs‘);constreadFile=function(fileName)returnnewPromis... 查看详情

jquery.deferred对象

JavaScript标准参考教程(alpha)jQueryjQuery.Deferred对象GitHub TOP jQuery.Deferred对象来自《JavaScript标准参考教程(alpha)》,by阮一峰目录概述deferred对象的方法基本用法notify()和progress()then方法pipe方法与PromiseA+规格的差异promise对... 查看详情

转:阮一峰flex布局教程:实例篇

作者: 阮一峰日期: 2015年7月14日上一篇文章介绍了Flex布局的语法,今天介绍常见布局的Flex写法。你会看到,不管是什么布局,Flex往往都可以几行命令搞定。我只列出代码,详细的语法解释请查阅《Flex布局教程:语法... 查看详情

阮一峰:jquery官方基础教程笔记

jQuery是目前使用最广泛的javascript函数库。  据统计,全世界排名前100万的网站,有46%使用jQuery,远远超过其他库。微软公司甚至把jQuery作为他们的官方库。  对于网页开发者来说,学会jQuery是必要的。因为它让你了解业界... 查看详情

flex实例(阮一峰)

Flex布局教程:实例篇 作者: 阮一峰日期: 2015年7月14日上一篇文章介绍了Flex布局的语法,今天介绍常见布局的Flex写法。你会看到,不管是什么布局,Flex往往都可以几行命令搞定。我只列出代码,详细的语法解释请... 查看详情

oauth2原理概览

...优秀的参考文章,想要快速了解OAuth2的朋友,可以参考阮一峰-OAuth2.0的一个简单解释。本文仅为个人理解,将OAuth的概念原理进行整理归纳,在查阅资料时,发现阮一峰老师的OAuth专题博文已将这一主题解析得相当透彻,因此下... 查看详情

关于阮一峰老师es6(第三版)中管道机制代码的理解浅析

最近正在学习阮一峰老师的es6(第三版)教材,在学到第七章《函数的扩展》中的箭头函数嵌套时,文中提到了一个关于“管道机制”的示例,文中源代码如下://es6(第三版)教材中的管道机制源代码:constpipeline=(...funcs)=>val=... 查看详情

nodejsmocha测试学习

参考大神阮一峰的文章《测试框架Mocha实例教程》目前在使用Nodejs,但写完的程序很容易出错,那怎么办?需要引入单元测试去做基础的测试目前Nodejs用来做单元测试的工具接触的不多,现在只接触到Mocha,它是用来做单元测试... 查看详情

flex布局(引用阮一峰老师的flex布局-语法篇)(代码片段)

一、Flex布局是什么?Flex是FlexibleBox的缩写,意为"弹性布局",用来为盒状模型提供最大的灵活性。任何一个容器都可以指定为Flex布局。.boxdisplay:flex;行内元素也可以使用Flex布局。.boxdisplay:inline-flex;Webkit内核的浏览器,必须加上-w... 查看详情

node.js概述

JavaScript标准参考教程(alpha)草稿二:Node.jsNode.js概述GitHub TOP Node.js概述来自《JavaScript标准参考教程(alpha)》,by阮一峰目录简介安装与更新版本管理工具nvm基本用法REPL环境异步操作全局对象和全局变量模块化结构概述... 查看详情

nodejs-process对象

JavaScript标准参考教程(alpha)草稿二:Node.jsprocess对象GitHub TOP process对象来自《JavaScript标准参考教程(alpha)》,by阮一峰目录process对象是Node的一个全局对象,提供当前Node进程的信息。它可以在脚本的任意位置使用,不... 查看详情

读阮一峰老师es6入门笔记——第一章

  鉴于最近用vuejs框架开发项目,其中有很多涉及到es6语法不太理解所以便认真地读了一下这本书。  地址:http://es6.ruanyifeng.com/#README   第一章:let,const命令以及块级作用域  es6新增了let和const这两个变量的声明关... 查看详情

分享一个彻底冻结对象的函数——来自阮一峰老师的《ecmascript6入门》

varconstantize=(obj)=>{Object.freeze(obj);Object.keys(obj).forEach((key,i)=>{if(typeofobj[key]===‘object‘){constantize(obj[key]);}});};冻结对象的用处:冻结对象是指那些不能添加新的属性,不能修改已有属性的值,不能删除已有属性,以及不能修改... 查看详情

react入门实例教程[阮一峰的网络日志](分享)

作者: 阮一峰https://github.com/ruanyf/react-demos 转自:http://www.ruanyifeng.com/blog/2015/03/react.html对着文章的说明,看明白了,再跑下demo.... 查看详情

阮一峰老师的es6入门:变量的解构赋值(代码片段)

变量的解构赋值数组的解构赋值对象的解构赋值字符串的解构赋值数值和布尔值的解构赋值函数参数的解构赋值圆括号问题用途数组的解构赋值基本用法ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为... 查看详情