javascript:构造函数模式(为什么这种方式也可以创建对象)

ECMAScript中构造函数可以用来创建特定类型的对象。像ObjectArray这样的原生构造函数,在运行时会自动出现在执行环境中。此外,也可以创建自定义的构造函数,从而定义自定义对象类型的属性和方法。例如,可以使用构造函数模式将前面的例子重写。如下:

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function () {
        return this.name;
    };
}

var p1 = new Person("Ann" , 23 , "actress");
var p2 = new Person("Rose" , 23 , "writer");

当我看到上面的内容的时候,我震惊了。javascript中调用函数可以创建一个新的对象?使用new操作符,然后调用函数就可以了?

虽然这种方式很奇怪(相对于java,c#而言),但是,的确可以。

因为根据以往的经验,函数中的this是当前的执行环境变量。一般来说,如果是在网页上的全局环境里面调用函数,则函数内部的this对象就是window对象。但是,这里的this好像是一个新的类型(Person?)的对象。为什么?

下面是我的小测验,查看一下通过这种方式调用函数,是不是真的改变了this对象。

1 使用new调用构造函数的代码:

console.log("<>>>before this是 Window 类型吗? " + (this instanceof Window));
function Person(name, age, job) {
    console.log("inner this是 Window 类型吗? " + (this instanceof Window));
    console.log("inner this是 Person 类型吗? " + (this instanceof Person));
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function () {
        return this.name;
    };
}
var p1 = new Person("Ann", 23, "actress"); 
// todo: 使用了 new 操作符
console.log("outer this是 Window 类型吗? " + (this instanceof Window));
console.log("outer this是 Person 类型吗? " + (this instanceof Person));

// 在浏览器运行的输出结果如下

/**
 
 // todo: 在浏览器运行的输出结果如下 :
 <>>>before this是 Window 类型吗? true
 inner this是 Window 类型吗? false
 inner this是 Person 类型吗? true
 outer this是 Window 类型吗? true
 outer this是 Person 类型吗? false
 
*/

2 不使用new,直接调用构造函数的代码:

console.log("<>>>before this是 Window 类型吗? " + (this instanceof Window));
function Person(name, age, job) {
    console.log("inner this是 Window 类型吗? " + (this instanceof Window));
    console.log("inner this是 Person 类型吗? " + (this instanceof Person));
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function () {
        return this.name;
    };
}
var p1 = Person("Ann", 23, "actress"); // 注意:这里没有 new
console.log("outer this是 Window 类型吗? " + (this instanceof Window));
console.log("outer this是 Person 类型吗? " + (this instanceof Person));

/*
 
 // todo: 在浏览器运行的输出结果如下 :
 <>>>before this是 Window 类型吗? true
 inner this是 Window 类型吗? true
 inner this是 Person 类型吗? false
 outer this是 Window 类型吗? true
 outer this是 Person 类型吗? false
 
*/

同样的代码,只是在调用的时候,一次使用了new操作符来调用Person()函数,一次没有。然后输出的效果并不相同。
log可以看到:

  • 在函数外部,this一直是 Window类型的对象。(在全局环境中调用的)[即使函数内部的this不是Window类型。]
  • 在函数内部:
    • 如果当前函数被new funcName(args);的方式调用,this为当funcName类型的对象;
    • 如果当前函数没有使用new操作符调用,只是普通调用(var result = funcName(args);),则thisWindow类型的对象。

所以,通过构造函数模式确实创建了一个新的对象,而且,这个对象有自己的类型,可以被类型识别到了。

总结

  • 任何函数,不使用new去调用,就是普通的函数调用,函数中的this是当前函数调用的执行环境变量。(谁调用我,我的this就是谁。)。
  • 任何函数,使用new去调用,就成了构造函数,函数会创建一个新的对象类型,新的对象类型名就是当前函数名,函数中的this类型也就是这个新的对象类型。

你可能感兴趣的:(大猫学javascript)