getting-started-with-javascript icon indicating copy to clipboard operation
getting-started-with-javascript copied to clipboard

【10.2练习】

Open xugy0926 opened this issue 8 years ago • 16 comments

对象是js重最重要的概念之一。

在定义对象是,常用的方式是”属性定义“大法:

var obj = {
  name: 'xiaoming',
  age: 18,
  isStudent: true  
}

上面obj有3个属性,分别是name、age、isStudent。

除了”属性定义“大法,可以运用”键值定义“大法:

var obj = {
  "name": 'xiaoming',
  "age": 18,
  "isStudent": true  
}

”键值定义“对象方式和json对象格式一样,这也是为什么在js中,所谓的json对象和普通对象经常混为一谈。

这两种方式的共同点是什么?差异又是什么?

xugy0926 avatar Oct 02 '17 04:10 xugy0926

共同点:都是对象,可以被JavaScript调用; 最大的区别在于json文件中的属性名必须要有引号。

普通对象: 1.属性名的引号大部分情况下可以没有,但是当属性名当中包含空格,或者包含连字符,或者是保留字的时候,需要加引号。(源自犀牛书page120页6.1.1节) 2.普通对象定义结束后需要在{}后面增加分号,表示JavaScript语句结束

Json对象: 1.只是一种数据格式,并不从属于JavaScprit,有的其他编程语言可以解析Json数据格式 2.属性名称上必须有双引号(双引号 双引号 双引号)

Ideal-Li avatar Oct 02 '17 06:10 Ideal-Li

结论

括号表示法一个有用的地方是它不仅可以动态的去设置对象成员的值,还可以动态的去设置成员的名字。

开始

// 属性定义一个对象
var obj = {
  name: 'xiaoming',
  age: 18,
  isStudent: true,
  sayHello:function (name) {
  	console.log('nice to meet you',name);
  }  
}
// 键值对定义一个对象
var obj1 = {
  "name": 'xiaoming',
  "age": 18,
  "isStudent": true,
  "sayHello":function (name) {
  	console.log('nice to meet you',name);
  }  
}

说实话,只知道两种方法都可以用,而且感觉没什么差别,平常在用的时候也没多在意,甚至出现混着用的情况。还真没多思考。

尝试找出不一样或者可能报错的地方

  1. 使用点语法 访问属性值
console.log('******************使用点语法访问******************');
console.log('属性定义 存在的变量name:',obj.name);
console.log('属性定义 不存在的变量sex:',obj.sex);
console.log('键值对定义 存在的变量name:',obj1.name);
console.log('键值对定义 不存在的变量sex:',obj1.sex);
  1. 使用键访问 访问属性值 (后续查过资料,这里更正为括号表示法)
console.log('******************使用键访问******************');
console.log('属性定义 存在的变量name:',obj["name"]);
console.log('属性定义 不存在的变量sex:',obj["sex"]);
console.log('键值对定义 存在的变量name:',obj1["name"]);
console.log('键值对定义 不存在的变量sex:',obj1["sex"]);
  1. 赋值比较
console.log('******************赋值比较******************');

obj.sex = "male";
obj1.sex = "female";
obj['height'] = 170;
obj1['height'] = 170;

console.log(obj.sex,obj['sex']);
console.log(obj1.sex,obj1['sex']);
console.log(obj.height,obj['height']);
console.log(obj1.height,obj1['height']);
  1. 访问函数
console.log('******************访问函数******************');
obj.sayHello('jack');
obj1.sayHello('jack');
obj["sayHello"]('jack');
obj1["sayHello"]('jack');

以上代码 没有找到报错的地方 运行结果 也都一样。 我似乎可以认为 两者是真的一样,并无差别了。 事实上,上面提到的可以说是他们的共同点了吧。

到底有什么差别呢,只能查资料了。

探究不同点

属性定义对象和键值对定义对象实际上是对象的两种表示方法, 按照MDN先关链接所述,分别是 1. 点表示法 2. 括号表示法 这里甚至涉及到了命令空间。

点表示法

当你想访问对象内部的属性或方法时,去 点 属性 或者方法

对象的名字表现为一个命名空间(namespace) 在这里 顶部定义的对象obj就是一个命名空间, 子命名空间 把一个对象 作为 另一个对象成员对象的值 就创建了子命名空间 例如:

obj.name = {
	first: "huang",
	last: "xiaoming"
}

name就是子命名空间了,我们可以这么访问 obj.name.first 也可以用 obj["name"]["first"] 这个就是括号表示法

括号表示法

此段内容 均为引用

另外一种访问属性的方式是使用括号表示法(bracket notation),替代这样的代码 person.age person.name.first 使用如下所示的代码: person['age'] person['name']['first'] 这看起来很像访问一个数组的元素,从根本上来说是一回事儿,你使用了关联了值的名字,而不是索引去选择元素。难怪对象有时被称之为关联数组(associative array)了——对象做了字符串到值的映射,而数组做的是数字到值的映射。

结论

括号表示法一个有用的地方是它不仅可以动态的去设置对象成员的值,还可以动态的去设置成员的名字。 点表示法只能接受字面量的成员的名字,不接受变量作为名字。 简单来说就是 括号表示法 括号里 可以是个变量 比如:

var person = {};
var myDataName = 'height';
var myDataValue = '1.75m';
person[myDataName] = myDataValue;
console.log(person.height);

打印结果为 1.75m person对象是这样{ height: '1.75m' } 这里 person 的属性是动态设置的,使用点表示法是无法做到这一点的。

所以,括号表示法 比 点表示法 更强大,但是 点表示法 更方便 其实,实际中我们有也可能用到过,只是没注意罢了 平常用点表示法要方便许多,当要用到一个变量作为对象的属性的时候,只能括号表示法,自然就会用括号表示法了。

以上就是我得出的结果。可能不是很全,欢迎建议补充。

MyColourfulLife avatar Oct 02 '17 07:10 MyColourfulLife

关于 json,mozilla 给出的定义是这样的:

JavaScript Object Notation (JSON) is a standard text-based format for representing structured data based on JavaScript object syntax, which is commonly used for representing and transmitting data on web sites.

JSON的语法跟 obj 的语法类似,根据以上定义,我的理解是,前者是后者的一个子集。

关于obj”键值定义“对象方式和json对象格式:

  • 共同点在于,他们都基于JavaScript object syntax
  • 不同点在于,json 的格式更加严格,比如字符串要求必须使用双引号,且json只有在 string 格式的时候,JSON 才是 JSON

关于 json 的理解,我还写了一篇文档,阐述了我所理解的 json https://github.com/Yammmy/js-work/blob/master/my-homework/what-is-json.md

yammyxing avatar Oct 02 '17 11:10 yammyxing

JSON对象可以说是javascript对象的严格模式.

var obj = {
  name : 'xiaoming',
  age : 16,
  sex : 'male',
  married : false
}

相同点:

  1. 具有对象的基本格式 :
  • 对象用'{ }'包括
  • 不同的键值对(key:value)之间用","分隔
  • 键值对中的键和值用冒号":"分隔。

不同点:

在一般的对象中,key始终是字符串,如果key是一般格式(名字中不带有空格或者其他特殊字符),省去引号也没有任何问题。而在JSON中,key的双引号("")是必须的。

在一般的对象中,value可以是任何javascript内合法的值。相比较而言,JSON对格式的要求严格得多,正则表达式,函数,甚至是带有计算的表达式都不能加入。

~~JSON在javascript中可以被直接解释为对象,作为数据传输非常方便。~~

zjutszl avatar Oct 02 '17 12:10 zjutszl

相同点是用起来无差别: 用键值定义对象的时候,数据可以用json格式 也可以用js对象格式(就是带或者不带英文双引号);

不同点: ’json对象‘实际上是一种矛盾修辞法,json是一个描述对象 的文本格式,不是一个实际的对象。json格式中,键要带英文双引号。 如下的对象我们可以把js对象转换成一个键为字符串的JSON(javascript object notation): var myObj = { foo: 'bar', base: 'ball', deep: { java: 'script' } }; 我们调用window.JSON.stringify(myObj)可以转换成字符串形式,方便拿到json格式: var myobj = { "foo": "bar", "base": "ball", "deep": { "java": "script" } };
也可以通过window.JSON.parse(myobj);来返回原来的js对象。

french5 avatar Oct 02 '17 13:10 french5

  • 属性定义一个对象:
var obj = {
  name: 'xiaoming',
  age: 18,
  isStudent: true  
}

对象的属性可以赋值函数,也称为“方法”;调用时很方便,用’对象名.属性名‘即可引用。

  • 键值定义一个对象:
var obj = {
  "name": 'xiaoming',
  "age": 18,
  "isStudent": true  
}

键值定义,在客户端与服务器进行数据传输时常用的数据格式,安全。如果用属性定义,服务器可能会被植入恶意函数。

antarts avatar Oct 02 '17 15:10 antarts

共同点:两者都是用于表示并操作的数据类型,都是对数据存储的一种格式规范。除了普通对象的属性名可以使用标识符外,两者的具体写法基本一致。

差异:普通对象是作为编程语言的基本数据类型,用于运行在特定语言环境中的代码文件里(本例是js),而且需要赋值给变量才能真正使用。而json对象是用于数据交互的数据类型,可以适应多种语言环境,而且它既可以赋值给变量进行运算与交互,也可以直接写在json数据文件里进行文件交互。json对象储存的信息都可以存在普通对象里。但反过来,因为受到属性名的限制并不是所有的普通对象都可以当作json对象使用。归根结底,比起数据及格式上的差异,主要的区别表现在用途上。

freedomsky11 avatar Oct 02 '17 16:10 freedomsky11

先记录一下。

Google关键字:different ways to define javascript object property

参考资料:

Google关键字:javascript normal object vs json

参考资料:

Dream4ever avatar Oct 03 '17 01:10 Dream4ever

使用时的差异点

定义对象时可以混搭

var obj = {
  'name': 'xiaoming', // 键值
  age: 18,  // 属性
  isStudent: true // 属性
}

正常访问属性

// 通过键访问name
console.log(obj['name'])
=> xiaoming

// 通过属性访问age
console.log(obj.)
=> 18

也可以反过来

// 通过属性访问name
console.log(obj.name)
=> xiaoming

// 通过键值访问age
console.log(obj['age'])
=> 18

通过以上事例,可以认为不管是属性还是键值,都可以随意用属性访问方式或键值访问方式来访问内容。但真的是这样吗?

下面的定义做点变化。

var obj = {
  'my name': 'xiaoming', // 键是‘my name’,有一个空格
  age: 18,  // 属性
  isStudent: true // 属性
}

此时,'my name'只能通过键值访问方式来访问内容,而不能用属性方式

console.log(obj['my name']);
=> xiaoming

console.log(obj.my name);
=> error!!!!

键值方式可以采用任意字符,哪怕是中文也可以。

var obj = {
  '姓名': 'xiaoming', // 键是‘my name’,有一个空格
  age: 18,  // 属性
  isStudent: true // 属性
}
console.log(obj['姓名']);
=> xiaoming

总结

  1. 键可以用任意字符,不满足js的变量命名方式也可以。
  2. 属性必须满足js的变量命名方式才可以。

键是可以是一个表达式的值

当键是一个表达式值时,设置和访问时都是可以动态计算的。

var list = ['xiaoming', 'xiaohua'];

var obj = {};

for (var i = 0; i < list.length; i++) {
  obj['name=' + list[i]] = list[i];
}

console.log(obj);
=> { 'name=xiaoming': 'xiaoming', 'name=xiaohua': 'xiaohua' }

总结

  1. 键可以是表达式,动态构建,访问时也可以动态构建键。
  2. 属性不具备这个特性。

不管是键值还是属性,都适用于值为函数时

var obj = {
  '姓名': function () {
    console.log('xiaoming');
  },
  age: function () { 
    console.log(18)
  },
}

obj['姓名']();
obj.age();

总结

  1. 用键值还是属性,主要考虑键和属性的命名差异点,至于后面的值是什么类型无所谓。

构建动态的键,有什么应用场景

比如前端会按照分页的方式从服务端获取数据,那么每一页的数据都可以通过动态构建键的方式存储在obj对象中。

var obj = {};

getData(page) {
  axios.get('url', params: {page}).then(function (response) {
    obj['page=' + page] = response.data;
  });
}

getData(1);
getData(2);
getData(3);

以上obj感觉像是一个键值对的数据库对象,再使用内容时操作起来很方便。

xugy0926 avatar Oct 03 '17 06:10 xugy0926

可惜只有三种赞的方式,不然要给老师刷65535个赞,哈哈。

Dream4ever avatar Oct 03 '17 08:10 Dream4ever

老师发起的讨论自己不会答,只能把答案作为“教材”看, 并整理一下目前的理解。

var obj = { 'my name': 'xiaoming', // 键值 age: 18, // 属性 isStudent: true // 属性 }

属性: -1. 格式:不用''。因此,命名符号中间不能出现空格。到处都是空格,那么没有''标记时,命名中的空格无法被特殊对待和识别。

-1.1. 举例: myname 。

-1.2. 须要满足JS变量命名方式。

-1.WT. 问题(自己给自己挖坑):属性是自定义的关键字吗?之后注意。

-2. 访问方式:console.log(obj.myname)

键值: -1. 必须用'',因此,命名中可出现空格或中文。

-1.1 举例:‘myname’,‘my name’, ‘姓名’

-1.2. “可用任意字符,哪怕中文也可以”

-1.WT.挖坑:可以出现中文的话,那键值是不是可以直接显示在网页?所以在代码里直接用什么键值,在网页上可以直接显示出来?留意。

-2. 访问方式:console.log(obj['myname']) = console.log(obj.myname), console.log(obj['my name']) , console.log(obj['姓名'])

-2.WT.1. 挖坑:可理解为当命名为字符串时,不需要区分属性或键值?待定 。

-2.WT.2. 所以键值的意义就是为了构建动态的键吗? 看不懂,不过以后了解吧。

** 两种方式“定义对象时可以混搭”:参照老师例子。

ifoundu avatar Oct 03 '17 10:10 ifoundu

:+1: @Dream4ever 你是说这样吗? 还是怎么样? https://www.webpagefx.com/tools/emoji-cheat-sheet/ :yum:

ifoundu avatar Oct 03 '17 10:10 ifoundu

@ifoundu 哈哈哈哈,也给你点赞。

Dream4ever avatar Oct 03 '17 10:10 Dream4ever

@Dream4ever thank you~ 看到你讲的,我才注意到可以这样。:bouquet: 有些表情按:可选,暂时挂着链接来找。:smile: 艾嘛,点英文可自动复制的。:smiley:

你可以这样 :+1: x65535 :laughing:

ifoundu avatar Oct 03 '17 11:10 ifoundu

@ifoundu 哈哈,又发现一个新世界。

Dream4ever avatar Oct 03 '17 11:10 Dream4ever

“属性定义大法“与“键值定义大法“的区别:

交自己的作业迟了,又担心看了老师的回答后,自己就懒于思考,被动接受,无法发现自己的认识错误,就赶快刷到底部写了,所以下面的这部分是还没有看老师的内容而写的,故而可能错。

这道题目的目的是考察“属性定义”和“键值定义”的区别的,但本质上这两个都是在定义一个对象的属性名。我翻看了犀牛书P118-P142关于对象的讲解,发现区别还是蛮大的,先从概念上理解:

  • “属性定义”就是对象的属性名是不带冒号,即属性名是javaScript对象的标识符。
  • "键值定义"就是对象的属性名是带冒号的,即属性名是一个字符串直接量。

这种区别分为2个方面:

  • 命名的规则有不同
  • 调用的方法有不同

命名的灵活性不同

键值定义比属性定义的规则少很多,也宽松很多。
在下面这些情况下,必须是需要用键值定义,属性名需要加冒号:

var book = {
    "main title": "javaScript",                  // 属性名里面有空格,必须用字符串表示;
    "sub-title": "go go go",                    // 属性名里面有“-”,必须用字符串表示; 
    "for": "abc",                             // for是javaScript的保留字,也必须用字符串来表示;
     auther :  "ddd"
}

也即,若是不加冒号,那么属性名是需要遵循变量的命名规则的,但键值定义时加了冒号, 则是不需要,还可以是中文。

调用不同

当一个对象要访问他的属性时,有两种方法,属性定义时,就是通过标识符作为索引,而通过键值定义时,则是把字符串当做索引。如:

调用对象book的auther的属性,则用运算符(.)来进行调用book.auther,auther是对象book的标识符,通常标识符是静态的 ,必须写死在程序中,也就是说auther不能改变其字符串内容的,一旦定下来,其名字不能更改。(不过貌似也可以用,book[auther]来进行调用auther属性)。
当键值定义时,调用对象book的for的属性,则需要用到运算符([])来进行调用book["for"],字符串是动态的,在运行程序时可以更改。


还是老师讲得透彻……之前看教材,如果属性是通过[]调用,可以是动态的,通过(.)调用,是静态的,不是很明白,不过看了老师的答案后恍然大悟,O(∩_∩)O,如果是用[]调用,[]里面可以跟着一个表达式,但如果用.,后面不能跟表达式。

且,漏了3点:

  1. 键值定义和属性定义的属性名,都适用于值为函数的情况。
  2. 键值定义时,属性名可以是中文。
  3. 调用时,如果键值定义的属性名,和属性定义法的属性名符合js的变量命名规则,那么调用可以通过(.)和([])。

WangZhong2014 avatar Oct 03 '17 13:10 WangZhong2014