浅谈 JavaScript new 执行过程及function原
- 通过new运算符执行结果与直接执行函数结果不一样。new返回了一个对象
- new运算符会根据方法返回值的不同,执行方式是不一样的
- 然后,new 会改变this的指向。若直接作为函数执行this指向window,使用new运算符后的this指向当前对象
w3c关于Function的说明
用Function类直接创建函数的语法如下:
var function_name = new function(arg1, arg2, ... , argN, function_body)
在上面的形式中,每个arg都是一个参数,最后一个参数是函数本体(要执行的代码)。这些参数必须是字符串。
function Person() {}
具体的执行就是调用Function()构造函数进行构造的,最后一个参数是函数体。
当执行var person = new Function("name", "console.log(name)")
即创建了一个function实例对象,自带了Object+Funciton的属性方法。
在JS中,有两个基础原型,分别是Function.prototype和Object.prototype。这两个原型组成了JS中的所有实例他们的关系是 Function.prototype ----> Object.prototype ----> null
常用的创建类的有两种方法,我们从这两种方法讲两种prototype
的关系。
第一种是先有一个原型,直接令新的对象的__proto__
指向已经有的原型。这种时候可以类比继承关系,但区别是把那个原型的状态(如属性的取值等)也一并继承过来了。
但是记住这个时候新的对象从原型继承的值如果没有被初始化/赋值,原型中的值改变的话,新的对象中的对应值也会改变。
第二种是使用new来继承,new在JS里这样运行:
- 创建一个最基础的Object对象(内容为空 )并且初始化。
- 把后面的构造函数放进刚创建的obj中,并且设置
__proto__
为函数的对象。 - 使用创建出的对象作为obj,在obj中执行那个函数,,当然那个函数要对刚创建的这个对象进行初始化,然后返回。
- 如果返回的是Object对象,new就返回这个对象,否则返回刚创建的obj。
这里解释一下函数的原型类型:
比如说有 function A(){ var a = 1 }
那么A是一个Object,他的constructor就是A(),平时调用A()就相当于调用A这个Object的构造函数。
引申探讨prototype和__proto__
prototype属性是一个指针,指向一个对象,而这个对象的用途是包含可以有特定类型的所有实例共享的属性和方法。prototype是通过调用构造函数而创建的那个对象实例的原型对象。hasOwnProperty()判断指定属性是否为自有属性;in操作符对原型属性和自有属性都返回true。
var obj = {a: 1};
obj.hasOwnProperty("a"); // true
obj.hasOwnProperty("toString"); // false
"a" in obj; // true
"toString" in obj; // true
__proto__是指向本对象的原型对象的指针。可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法。
function Foo(){}
var Boo = {name: "Boo"};
Foo.prototype = Boo;
var f = new Foo();
console.log(f.__proto__ === Foo.prototype); // true
console.log(f.__proto__ === Boo); // true
Object.getPrototypeOf(f) === f.__proto__; // true
示例(结合关系图食用)
function Person(name) {
this.name = name;
}
Person.prototype = {
constructor: Person,
sayName: function(){
console.log("my name is " + this.name);
}
}
var p1 = new Person("ligang");
var p2 = new Person("Camile");
p1.sayName(); // my name is ligang
p2.sayName(); // my name is Camile
关系图
prototype和__proto__参考