创建像JavaScript对象文字一样的行为

时间:2014-06-09 16:43:21

标签: javascript

我希望能够做到以下几点:

person('male');
person.age(34);

如您所见,我希望person object同时为functionobject。我的意思是这样做:

function person(gender){

    this.gender = gender || 'unknown';
}

让我无法这样做:

person.gender; // undefined

除非我从person函数创建一个新对象,如下所示:

var me = new person();
me.gender; // 'unknown'

我不想要,因为我仍然希望能够设置其他属性,如:

person.age = 34;

这有可能吗?我是在尝试完成不可能的事情吗?

澄清:我不想创建实例。关键是我只想将函数person称为function.property()

编辑:也许我通过使用错误的例子让很多人(包括我自己)感到困惑。一个更简单的问题是:我如何能够调用该函数的函数和'属性',如下所示:

car();
car.start();

同时无需创建汽车实例?

5 个答案:

答案 0 :(得分:4)

如果你能解释你想做什么背后的动机,我们或许可以给出更好的答案。但是,是的,你所描述的是可能的。在JavaScript中,函数只是另一种类型的对象。这意味着您可以定义一个函数,然后像这样设置属性:

var person = function () {
    return "Hi, I am a person!";
};

person.species = "human";
person.foo = 42;

console.log( person() ); // prints: Hi, I am a person!
console.log( person.species ): // prints: human
console.log( person.foo ); // prints: 42

或者从第二个例子开始:

var car = function () {
    return {
        model: "Focus",
        make: "Ford",
        year: 2010
    };
};

car.start = function () {
    return "Vroom!";
};

console.log ( car.make ); // prints: Ford
console.log ( car.start() ); // prints Vroom!

顺便说一下, 与返回对象的函数相同。这可能是这样的:

var person = function () {
    return {
        species: "human",
        name: "Bob",
        age: 27
    };
};

var bob = person();
bob.occupation = "cubicle drone";

console.log( bob.name ); // prints: Bob
console.log( bob.occupation ); // prints: cubicle drone
console.log( person.occupation ); // prints: undefined
console.log( bob == person ); // prints: false

变量bobperson都包含对象,但不包含相同的对象,甚至不包含相同类型的对象。

答案 1 :(得分:3)

而不是在函数内部使用this,它引用通过使用new运算符调用此函数作为构造函数创建的Object实例,您可以使用arguments.callee来引用到功能本身

function person(gender){
    arguments.callee.gender = gender || 'unknown';
}

如果要确保函数始终用作构造函数,即使在没有new运算符的情况下调用它,也可以通过隐式调用它来实现。

function person(gender){
    if(!(this instanceof person)){ return new person(gender); }
    this.gender = gender || 'unknown';
}

在所有其他方面,函数可以做任何常规对象可以做的事情,这就是为什么它们经常被描述为"第一类对象"。

您只需为对象或类似

等方法指定属性即可
function car(){
}
car.start = function(){

}

您也可以让他们使用__proto__属性从函数继承方法。

function bird(){}
function platypus(){}

bird.layEggs = function(){};
platypus.__proto__ = bird;
platypus.layEggs()         // now you know

答案 2 :(得分:1)

使用@Winchestro正在使用的实例方式的一个小例子

on jsfiddle:http://jsfiddle.net/47EEr/

'use strict';
function person(gender, age, name) {
    if (!(this instanceof person)) {
        return new person(gender, age, name);
    }
    var props = { gender: '', age: 0, name: '' }, fnCreateProp = function(prop, value) {
        Object.defineProperty(this, prop, {
            get: function() {
                return props[prop];
            },
            set: function(val) {
                console.log('setting prop ' + prop + ' to ' + val);
                props[prop] = val;
            }
        });
    }.bind(this);

    for (var prop in props) {
        if (!props.hasOwnProperty(prop)) {
            continue;
        }
        fnCreateProp(prop, props[prop]);
    }

    this.gender = gender;
    this.age = age;
    this.name = name;    

    this.toString = function(element) {
        var str = '[Person=(';
        for (var prop in props) {
            if (!props.hasOwnProperty(prop)) {
                continue;
            }
            if (str.indexOf('(') !== str.length-1) {
                str += ',';
            }
            str += prop +': ' + props[prop];
        }
        str += ')]';
        if (typeof element !== 'undefined') {
            var el = document.getElementById(element);
            if (el) {
                el.innerHTML = str;
            }
        }
        return str;
    };

    this.birthday = function() {
        this.age++;
    };
}

var p1 = person('male', 33, 'male 1');
var p2 = new person();
p2.age = 32; p2.gender = 'female'; p2.name = 'female 1';

p1.toString('person1');
p2.toString('person2');
p2.birthday();
p2.toString('person2birthday');

答案 3 :(得分:0)

你也可以这样做:

function person(gender){  
  return {
    gender: gender || 'unknown'
  };
}
var p = person('male');
p.age = 34;
p.name = 'John';
etc...

不使用“新”,您仍然可以重复使用人物功能。

答案 4 :(得分:0)

您的修改

  

编辑:也许我通过使用错误的例子让许多人(包括我自己)感到困惑。一个更简单的问题是:我怎么能够   称一个函数和一个属性'该功能,如下:

car();
car.start();
     

同时无需创建汽车实例?

这是您要找的吗?

function car() {

  console.log("car called");

  car.start = function() {
    console.log("car.start called");
  }

}
car();
car.start();

/**** output:****
car called
car.start called
*/