JS对象---奥义:真の由浅入深 - 毛毛亮不想做开发
This is my first blood!
第一次在segmentfault
上写(chao)文章。
内容提要:认(wu)真(liao)的整理一下javascript对象的知识,人家还是菜鸟,必须要搞懂啊。
PS:
1.真的菜,所以看到文章的同学,推荐采用随缘阅读法,请自行忽略里面充斥大量的,哦不,巨量的错误、bug。
2.如果您愿意指出我的错误,那最好不过了,寡人谢谢!(参见文章中的‘求大腿’的字样)
3.不过,如果你指望以此契机,期待一场与程序媛之间的轰轰烈烈的深刻的交互,那您还是绕道而行吧。哥真的是汉子,不是童瑶。
4.说是笔记,大部分的代码都是copy的,不爽的同学,直接看参考资料吧。
一 参考资料
1.MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Working_with_Objects
2.文档:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object
二 全都是对象
在 JavaScript 中,几乎所有的东西都是对象。所有的原生类型除了 null 与 undefined 之外都被当作对象。它们可以被赋予属性(某些类型的被赋予的属性不能被持久化),并且它们都有对象的全部特征。
三 创建对象
两种创建方式:
1.对象初始化器(Object Initializer)创建对象。(容易理解)
2.创建一个构造函数并使用该函数和 new 操作符初始化对象。(容易装逼)
容易理解的创建方式
模版:
var obj = { property_1: value_1, // property_# may be an identifier... 2:value_2, // or a number... // ..., "property n": value_n }; // or a string
实例:
var lolhero = new Object();lolhero.basicSkill = "Q、W、E";lolhero.bigSkill = "R only";lolhero.commotSkill = "D&F";//两种访问方式console.log(lolhero['basicSkill']);//采用类似关联数组的方式访问console.log(lolhero.basicSkill);//直接访问
容易装逼的创建方式
使用构造函数,需要两步!!!
通过创建一个构造函数来定义对象的类型。首字母大写是非常普遍而且很恰当的惯用法。
通过 new 创建对象实例。
写的太好直接copy过来了
function Car(make, model, year) { this.make = make; this.model = model; this.year = year;}var Car = new Car("Eagle", "Talon TSi", 1993);var kenscar = new Car("Nissan", "300ZX", 1992);var vpgscar = new Car("Mazda", "Miata", 1990);
一个对象的属性值可以是另一个对象。例如,假设你按如下方式定义了 person 对象:
function Person(name, age, sex) { this.name = name; this.age = age; this.sex = sex;}
然后按如下方式创建了两个 person 实例:
var rand = new Person("Rand McKinnon", 33, "M"); var ken = new Person("Ken Jones", 39, "M");
那么,你可以重写 car 的定义以包含一个拥有它的 owner 属性,如:
function Car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; }
你可以按如下方式创建新对象:
var car1 = new Car("Eagle", "Talon TSi", 1993, rand); var car2 = new Car("Nissan", "300ZX", 1992, ken);
注意在创建新对象时,上面的语句将 rand 和 ken 作为 owner 的参数值,而不是传入字符串字面量或整数值。接下来你如果想找出 car2 的拥有者的姓名,你可以访问如下属性:
car2.owner.name
注意你总是可以为之前定义的对象增加新的属性。例如,语句
car1.color = "black";
为 car1 增加了 color 属性,并将其值设为 "black." 然而,这并不影响其他的对象。想要为某个类型的所有对象增加新属性,你必须将属性加入到 car 对象类型的定义中。
PS:发现没,虽然第二种创建对象的方式看起来不那么自然.
但是却好用,容易移植,容易重新定义,容易复用。所以,还是装逼好啊!
Object.create 创建对象
感觉挺麻烦的,反正已经有了其他创建方式,暂且不管他了。
(这玩意儿一般用的多吗?多用来处理什么功能?求大腿)
四 属性
如果对象的属性名千奇百怪怎么办?
这样也是允许的(太难为js了吧),有谁这么变态的用各种类型的属性名,算了,变态总是有的。
var myObj = new Object(), str = "myString", rand = Math.random(), obj = new Object(); myObj.type = "Dot syntax"; myObj["date created"] = "String with space"; myObj[str] = "String value"; myObj[rand] = "Random Number"; myObj[obj] = "Object"; myObj[""] = "Even an empty string"; console.log(myObj);
当然了,属性值,也可以是个变量
var propertyName = "make"; myCar[propertyName] = "Ford"; propertyName = "model"; myCar[propertyName] = "Mustang";
对象的属性太多,用for(var i in obj){}
来遍历它
hasOwnProperty: 如果 object 具有指定名称的属性,那么JavaScript中hasOwnProperty函数方法返回 true;反之则返回 false。此方法无法检查该对象的原型链中是否具有该属性;该属性必须是对象本身的一个成员。
function showProps(obj,objName) { var result = ""; for(var i in obj){if( obj.hasOwnProperty(i) ) { result += objName+"."+i+" = "+obj[i]+"\n";} } return result; } console.log(showProps(myObj,"myobj"));
从 ECMAScript 5 开始,有三种原生的方法用于列出或枚举对象的属性:
for...in 循环
该方法依次访问一个对象及其原型链中所有可枚举的属性。
Object.keys(o)
该方法返回一个对象 o 自身包含(不包括原型中)的所有属性的名称的数组。
Object.getOwnPropertyNames(o)
该方法返回一个数组,它包含了对象 o 所有拥有的属性(无论是否可枚举)的名称。
在 ECMAScript 5 中,没有原生的方法枚举一个对象的所有属性。然而,可以通过以下函数完成:
function listAllProperties(o){ var objectToInspect; var result = []; for(objectToInspect = o; objectToInspect !== null; objectToInspect = Object.getPrototypeOf(objectToInspect)){result = result.concat(Object.getOwnPropertyNames(objectToInspect)); } return result; }
上面的这个方法,可以访问所有的可枚举和不可枚举的属性。
PS:对象里面的属性有可枚举和不可枚举两种。(不甚理解什么是不可枚举,求大腿!)
五 继承
所有的 JavaScript 对象继承于至少一个对象。被继承的对象被称作原型,并且继承的属性可能通过构造函数的 prototype 对象找到。
六 为对象类型定义属性
你可以通过 prototype 属性为之前定义的对象类型增加属性。这为该类型的所有对象,而不是仅仅一个对象增加了一个属性。下面的代码为所有类型为 car 的对象增加了 color 属性,然后为对象 car1 的 color 属性赋值:
Car.prototype.color = null;car1.color = "black";
七 如果我想给对象添加方法怎么办?
两种方式:
objectName.methodname = function_name;
var myObj = { myMethod: function(params) { // ...do something }};
前面创建对象的完整写法:
function Car(make, model, year, owner) { //注意displayCar函数里面this和外面的this指向的是同一个car对象! function displayCar() {console.log("this2",this);var result = "A Beautiful " + this.year + " "+ this.make + " " + this.model;return result; } this.make = make; this.model = model; this.year = year; this.owner = owner; console.log("this1",this); this.displayCar = displayCar; } var car = new Car("福特汽车","奔驰",1234,"maomaoliang"); console.log(car.displayCar());
或者
function Car(make, model, year, owner) { this.make = make; this.model = model; this.year = year; this.owner = owner; this.displayCar = function(){ //... };}
八 删除属性
用 delete 操作符删除一个不是继承而来的属性。下面的例子说明如何删除一个属性:
//Creates a new object, myobj, with two properties, a and b.var myobj = new Object;myobj.a = 5;myobj.b = 12;//Removes the a property, leaving myobj with only the b property.delete myobj.a;
九 比较对象
在 JavaScript 中 objects 是一个引用类型。将两个引用相同的对象想比较会返回 true; 将两个方法和属性相同的对象相比较,会返回 false;
// fruit object reference variablevar fruit = {name: "apple"};// fruitbear object reference variablevar fruitbear = {name: "apple"};fruit == fruitbear // return falsefruit === fruitbear // return false
// fruit object reference variablevar fruit = {name: "apple"};// fruitbear object reference variablevar fruitbear = fruit; // assign fruit object reference to fruitbear object reference variable// here fruit and fruitbear pointing to same object called fruitfruit == fruitbear // return true// here fruit and fruitbear pointing to same object called fruitfruit === fruitbear // return true
意思就是,用的时候要比较引用,而不是比较全部咯?求大腿