js对象

来源:互联网 发布:同济大学设计数据分析 编辑:程序博客网 时间:2024/06/05 10:45

创建js对象有三种方式:对象字面量、内置的构造函数、自定义的构造函数
对象既有属性、又有方法
1.对象字面量创建对象:

var dog = {    name: "kitty",    getName: function() {        return "maomao";    }}

完全删除对象属性/方法:

delete dog.name;delete dog.getName;

2.内置构造函数创建对象:

var dog = new Object();dog.name = "kitty";dog.getName = function() {    return "maomao";}

建议使用对象字面量的方式创建对象。
因为对象字面量:仅需要输入更短的字符;它强调了该对象仅是一个可变哈希映射,而不是从对象中提取的属性或方法;它并没有作用域解析;
而object构造函数:可能会继承其他人编写的遗留代码;Object构造函数仅接收一个参数,根据所传递的值的类型,Object可能会委派另一个内置构造函数来创建对象,并且返回了一个并非期望的不同对象
这里写图片描述
有作用域解析,可能以同样的名字创建了一个局部构造函数,解析器需要从调用Object()的位置开始一直向上查询到作用域链,直到发现全局object构造函数;

3.自定义构造函数创建对象:

var Person = function (name) {    this.name = name;    this.say = function () {        return "I am " + this.name;    }}var lily = new Person ("lily");lily.say(); // 输出结果为I am lily

当以new操作符调用构造函数时,函数内部将会发生以下情况:
(1) 创建一个空对象并且this变量引用了该对象,同时还继承了该函数的原型;
(2) 属性和方法被加入到this引用的对象中;
(3) 新创建的对象由this所引用,并且最后隐式地返回this(如果没有显式地返回其他对象)

var Person = function (name) {    // 使用对象字面量模式创建一个新对象    // var this = {};  // 此语句不是真相的全部,因为空对象实际上并不空,它已经从Person的原型中创建了许多成员,因此,更像是下面的语句:var this = Object.create(Person.prototype);    // 向this添加属性和方法    this.name = name;    this.say = function () {        return "I am " + this.name;    }     // 隐式的返回this(如果没有显式地返回其他对象)    // return this;}

本例中将say()方法添加到this中,其造成的结果是在任何时候调用new Person()时都会在内存中创建一个新的函数,此种方式效率低下,因为多个实例之间的say()方法实际上并没有改变。
更好的选择是:将方法添加到Person类的原型中

Person.prototype.say = function () {    return "I am " + this.name;}

切记:可重用的成员,比如,可重用的方法,都应该放置到对象的原型中。

构造函数仍然只是函数,只不过它却以new的方式调用。如果在调用构造函数时忘记指定new操作符,会导致构造函数中的this**指向了全局对象(在浏览器中,this将会指向window)(注意:只有this这种模式才指向全局**):

var w = function() {    this.g = "gg";}var w1 = w();console.log(typeof w1); // 输出 undefinedconsole.log(w1.g); // 输出 undefinedconsole.log(window.g) // 输出 gg

所以,在使用构造函数时,要强制使用new的模式

对于简单的对象,不需要类似that这样的局部变量,可以仅仅从字面量中返回一个对象,如:

function Waffle() {    return {        tastes: "yummy"    }}var first = new Waffle(),    second = Waffle();console.log(first.tastes);  // 输出 yummyconsole.log(second.tastes); // 输出 yummy

但这种模式的问题它会丢失到原型的链接,因此任何您添加到Waffle()原型的成员,对于对象来说都是不可用的

为了解决前面模式的缺点,并使得原型属性可在实例对象中使用,那么,可以使用如下两种方法(思想:可以在构造函数中检查this是否为构造函数的一个实例,如果不是,构造函数可以再次调用自身,并且在这次调用中正确的使用new操作符)
方法一:

function Waffle() {    if (!(this instanceof Waffle)) {        return new Waffle();    }    this.tastes = "yummy";}Waffle.prototype.wantAnother = true;

方法二:

function Waffle() {    if (!(this instanceof arguments.callee)) {        return new arguments.callee();    }    this.tastes = "yummy";} Waffle.prototype.wantAnother = true;

使用arguments.callee模式是基于这样的一个事实:即在每个函数内部,当该函数被调用时,将会创建一个名为arguments的对象,其中包含了传递给该函数的所有参数。同时,arguments对象中有一个名为callee的属性,该属性会指向被调用的函数。(注意:在ES5的严格模式中不支持arguments.callee属性)

0 0