js中所有事物都是对象:字符串 数组...()万物皆对象
js 有一些内建对象 String Date Array等
属性类型
[[Configurable]] 表示能否通过 delete 删除属性从而从新定义属性,能否修改属性的特性
[[Enumerable]] 表示能否通过 for-in 循环返回属性
[[Writable]] 表示能否修改属性的值。
[[Value]] 包含这个属性的数据值,默认为 undefined
不建议操作以上属性。
创建对象:
方式一:工厂模式
function createPerson(name, age, job){ var o = new Object(); //创建对象 (原料) o.name = name; //加工 o.age = age; o.job = job; o.sayName = function(){ alert(this.name); }; return o; //返回对象(出厂) } var person1 = createPerson("N", 29, "Engineer"); var person2 = createPerson("G", 27, "Doctor");
缺点:无法显示出 person1与 createPerson的依赖关系 (person1.constructor 等于 Object 构造函数)
方式二:构造函数模式
function Person(name, age, job){ //构造函数始终都应该以一个大写字母开头,非构造函数则以小写字母开头 this.name = name; this.age = age; this.job = job; this.sayName = function(){ alert(this.name); }; } var person1 = new Person("N", 29, "Engineer"); var person2 = new Person("G", 27, "Doctor");
以这种方式调用构造函数实际上会经历4个步骤
1.创建一个新对象
2.将构造函数的作用域赋给新对象 (实际上就是 构造函数中的 this );
3.执行构造函数中的代码(添加属性)
4.返回新对象
通过构造函数模式创建的对象都有一个 constructor 属性 该属性指向 Person
alert(person1.constructor == Person); //true
方式三:原型模式
使用构造函数的prototype 属性来指定那些应该共享的属性和方法。 组合使用构造函数模式和原型模式时,使用构造函数定义实例属性,而使用原型定义共享的属性和方法。
每一个 通过构造函数 new 出来的实例 都包含一个内部属性,该属性仅指向 Person.prototype
function Person(){} //构造函数 Person.prototype.name = ‘xx‘; Person.prototype.age = 23; var p1 = new Person(); p1.name = ‘pp‘; console.log(p1.name); // pp 来自实例 delete p1.name; // deleate 不能删除原型链上的属性 删除的是 实例上的属性 console.log(p1.name) // xx 来自原型
访问属性或方法时 总是先查找当前实例 当当前实例找不到所要的方法或者属性后再向上查找原型链上的方法与属性。所以,第一处打印会来自实例的name 属性 当删除改属性后(deleate不能删除原型上的属性),在当前实例找不到name属性 向上查找原型链上的name 属性,所以第二处打印的是 xx。
注意:in操作符会在通过对象能够访问给定属性时返回 true 无论该属性存在于实例中还是原型中(即只要实例或者原型中有要访问的属性即返回true)
解决办法:同时使用 hasOwnProperty() 跟 in 操作符,就可以确定该属性到底是存在于对象还是存在于原型
function hasPrototypeProperty(object,name){ //实例属性返回 false 原型属性 返回 true return !object.hasOwnProperty(name) && (name in object); }
要取得对象上的所有可枚举的实例属性,可以使用 ES5的 Object.keys() 该方法接收一个对象作为参数