function Person() {}
var student = new Person();
student.__proto__; //会输出Person() {}; 注意这是在chrome中
function Foo() {}
foo.prototype.__proto__ === Object.prototype //true
并不是所有对象都有原型
var obj = Object.create(null);
obj.__proto___ ; // undefined
obj.toString; //undefined
并不是所有的函数都有prototype属性,如ES5中有一个bind方法,我们这样做
function abc () {}
abc.prototype; // abc {}
var binded = abc.bind(null);
typeof binded // "function"
binded.prototype //undefined
bind函数是修改函数运行时的this
一个例子:
function Foo () {}
Foo.prototype.z = 3;
var one = new Foo();
one.x = 1;
one.y = 2;
console.log(one.x);// 1
console.log(one.y);// 2
console.log(one.z);// 3
console.log(one.prototype); //undefined
console.log(typeof Foo.prototype);//object
console.log(Foo.prototype.constructor);//function Foo() {}
修改prototype
function Student() {}
var bosn = new Student();
Student.prototype.x = 101;
bosn.x; // 101
Student.prototype = {y: 2};
bosn.y; //undefined 原有对象不能访问原型的新增属性
bosn.x; //101
function Person(name) {
this.name = name;
this.showMe = function() {
console.log(this.name);
}
}
Person.prototype.from = function() {
console.log('I come from prototype.');
}
function SubPerson() {}
SubPerson.prototype = new Person();
var subOne = new SubPerson();
subOne.from(); // I come from prototype
console.log(subOne.constructor);
console.log(SubPerson.prototype.constructor);
function Person(name) {
this.name = name;
this.showMe = function() {
console.log(this.name);
}
}
Person.prototype.from = function() {
console.log('I come from prototype.');
}
var father = new Person('js');
console.log(father.constructor);// function Person(name) {...}
function SubPerson() {}
SubPerson.prototype = father;
SubPerson.prototype.constructor = SubPerson; //constructor是指向函数
var son = new SubPerson();
son.showMe(); // js
son.from(); // I come from prototype
console.log(father.constructor); //function SubPerson() {}
console.log(son.constructor); //function SubPerson() {}
console.log(SubPerson.prototype.constructor);//function SubPerson() {}
prototype和constructor
去年有一段时间被拉去做NodeJS, 于是顺带着接着写写javascript。现在开始full time做安卓,就把之前学习的一些记录一下,暂时就先告别服务器端开发,以后有好的机会再接着做做。回到主题上来:
prototype
prototype
是javascript中的函数(function)的一个保留属性,并且它的值是一个对象(我们可以称这个对象为"prototype对象")Object.prototype
为null。prototype
属性。使用new
生成的对象,没有这个属性。 但需要注意理解这样一句:使用new
生成的对象,函数的prototype属性作为new 出来的对象的原型 如:需要注意:对象的原型是一个抽象的概念,不直接对外暴露,但是Chrome提供了proto来访问,在ES5中有Object.getPrototypeOf(obj)来获得原型。 如:
bind
函数是修改函数运行时的this 一个例子:修改prototype
动态修改函数的
prototype
时,第3行代码对Student
的原型动态添加一个属性时,所有的Student
对象都会受到影响。如果直接修改构造器的prototype
对象---Student.prototype = {y: 2}
时,对已经创建的实例是不会有影响的。已经创建的实例,其已经指向了Student.prototype
所指向的那个对象。constuctor
接着看
constructor
属性,前面提到了每个函数都有一个prototype属性,其prototype属性中会有一个constructor属性,该属性会指向函数本身。所以上面例子的最后一行,输出的会是函数Foo
本身。 针对上面的例子。如果有console.log(one.constructor)
也会有输出function Foo(){}
,因为one
的原型会指向Foo.prototype
,而Foo.prototype
所对应的对象上有constructor
属性。看下面这个例子:
说明:
subOne.from()
: 由于subOne对象上没有这个方法,会从其原型也就是其构造器(SubPerson
函数)的prototype中找,而其prototype又是一个Person类型的对象,这个对象上也没有from
方法,便从这个new Person()
类型的对象的构造器(Person
函数)的prototype中找,发现有,便执行这个方法。subOne.constructor
:subOne
这个对象是没有contructor属性的,于是会从其原型也就是其构造器(SubPerson
函数)的prototype中找,而其prototype又是一个Person类型的对象,该对象上也没有constructor
属性,于是从这个new Person()
类型的对象的构造器(Person
函数)的prototype中找。而前面提到的于是,便找了到
Person.prototype.constructor
, 因此,此处会输出function Person(name) {...}
;SubPerson.prototype.constructor
:SubPerson.prototype
指向的是一个new Person()
对象,但该new Person()
对象没有constructor
属性,于是从这个new Person()
类型的对象的构造器(Person
函数)的prototype中找,也就找到了。因此这一行的输出和上一行的一样。继承
继承的实现很简单,只需要把子类的prototype设置为父类的一个(实例化)对象即可。 看下面的例子:
需要注意的是倒数第三行
console.log(father.constructor);
输出的会是function SubPerson() {}
, 这是因为在subPerson.prototype.constructor = SubPerson;
也就相当于father.constructor = SubPerson
对象的创建方式
除了采用
new
来创建对象,也可以采用Object.create()
来创建对象。通过new去创建对象, 它的原型会指向构造器(函数)的prototype属性。Student.prototype = Object.create(Person.prototype);
改成Student.prototype = Person.prototype
, 那么当我们往Student.prototype
上添加属性的时候也会加到Person.prototype
上。通过Object.create()创建一个空的对象,而这个空对象的原型指向了Person。 这样,当我们使用Student.prototype
时可以向上查找到Person。同时可以在不影响Person的情况下,在Student.prototype
上创建自己的属性。constructor
,将Student.prototype.constructor = Student
,如果不这样设置constructor
会指向Person本身。覆盖基类的方法
子类自己的方法
推荐采用这种方式来创建对象。公有的属性写在函数中,公有的方法写在函数的prototype属性上。采用
Object.create
来创建对象。参考: http://blog.csdn.net/niuyongjie/article/details/4810835 http://www.imooc.com/learn/277