function Person(name){ //构造函数
this.name=name;
}
function fk (){};
Person.prototype.printName=function() //原型对象
{
alert(this.name);
}
var person1=new Person('Byron');//实例化对象
1. person1.__proto__ 实例化对象指向 Person.prototype 这两个是恒等的。 person1.__proto__===Person.prototype
person1.constructor 指的就是 Person ,这两个是恒等的,就是Person的构造函数,对应构造函数
person1.constructor === Person
就是要区分原型对象,在通过 Person.prototype.printName 是不在构造函数里面的。
2.如果覆盖Person.prototype 例如
Person.prototype = function(){ return 123};
就会出现
为了保持原有的属性,可以
Person.prototype = {name:'123',constructor:Person.constructor} 把原有的属性赋值进去。
函数汇总
一.函数定义
1.定义一个函数 函数对应的 funcName 对应的是 funcname()对象。
function Foo(){
//函数体
}
2.定义一个匿名函数,并且赋值给 b 变量,而 b对应的
var b=function(x){
//函数体
}
3.采用函数构造方式建立一个函数
funcName = new Function("x",'return 2*x');
Foo.prototype 是一个Food的引用对象
Foo.prototype.constructor指向的是 Foo() 的构造函数。
Foo.constructor 指向的是Function(){}函数
对应第二种方式创建的对象
b.prototype是一个Object对象的引用
b.prototype.constructor 指向的是匿名的构造函数
函数的私有属性
在函数内部定义的变量和函数,如果不对外提供接口,外部是无法访问到的,也就是该函数的私有的变量和函数。
functionPerson(){
var name= "tony";//私有变量var fn = function(){}
//私有函数
}
这里的私有是针对实例对象而言的
var obj = new Person();
alert(obj.name);//弹出 undefined
alert(obj.fn);//
弹出 undefined
但是如果 把属性放置在构造函数里面效果就不一样了
function person(){
this.name = '123';
this.fn=function(){}
}
那么实例化的每个对象都可以访问。
函数静态变量
function Person(){};
Person.name = 'tony';//静态变量
Person.fn = function(){} //静态函数
alert(Person.name);//'tony'
alert(typeof Person.fn)//function
var t = new Person();
alert(t.name);//undefined
alert(typeof t.fn);//undefined
this.name = name;
this.age = age;
}
var p1 = new Person("nn",19);
var p2 = new Person("mm",20);
实例化p1,p2两个对象,中的属性和方法与p2中的属性与方法虽然同名但却不是一个引用,而是对
Person
对象定义的属性和方法的一个复制。
如果定义太多的实例对象,那么就会产生很多重复的工作。
为了解决这个问题,引用了prototype(原型)这个概念
prototype 原型
再看如下代码
var Person= function(){};
Person.prototype.say= function(){
alert("I'm a person");
}
var tom= newPerson
();
tom.say();
对于方法 Person可以通过 prototype获取方法say,但是对实例化对象tom是怎么访问到say呢
由于tom中没有这个方法,所以,他就会去他的当调用构造函数创建一个实例的时候,实例内部将包含一个内部指针(__proto__
中去找,也就是Person.prototype
,所以最终执行了该run()方法
__proto__
)指向构造函数(Person)的
prototype
现在做一下区分:
1.实例就是通过构造函数创建的。实例一创造出来就具有constructor
属性(指向构造函数)和__proto__
属性(指向原型对象),
2.构造函数中有一个prototype
属性,这个属性是一个指针,指向它的原型对象。
3.原型对象内部也有一个指针(constructor
属性)指向构造函数:Person.prototype.constructor = Person;
通过一个例子说明
prototype
上定义的方法确实可以通过对象直接调用到,而且代码是共享的。
函数对象实例
定义一个对象
function Person = function(name){ this.name = name;}
var tom = new Person();
new操作符具体干了什么呢?其实很简单,就干了三件事情。
var tom= {};
tom
.__proto__ = Person.prototype;
Person.call(obj);
看看多重继承的概念
TwoShape.prototype = new Shape();产生了 TowShape.prototype._proto_指向了Shape.prototype
对应p对象,由于实例化TowShape(),把Shape的属性也复制过来了。
对应p2,
由于实例化Triangle(),Triangle指向TowShape,而TowShape指向Shape,这样先复制Shape的属性,然后复制TowShape 属性。
如果想保持原有构造数据
TwoShape.prototype.constructor = TwoShape;
Triangle.prototype.constructor = Triangle;
原型继承
原型链的问题:原型链虽然很强大,可以用它来实现继承,但它也存在一些问题。其中最主要的问题来自包含引用类型的值原型(int等基本值类型)。
包含引用类型的原型属性会被所有实例共享;而这也正是为什么要在构造函数中,而不是在原型对象中定义属性的原因。
在通过原型来实现继承时,原型实际上回变成另一个类型的实例(
TwoShape.prototype = new Shape()
)。于是,原先的实例属性也就变成了原型的属性
__ptoto__
属性
__ptoto__
属性(IE浏览器不支持)是实例指向原型对象的一个指针,它的作用就是指向构造函数的原型属性constructor
,通过这两个属性,就可以访问原型里的属性和方法了。
Javascript
中的对象实例本质上是由一系列的属性
组成的,在这些属性中,有一个内部的不可见的特殊属性——__proto__
,该属性的值指向该对象实例的原型,一个对象实例只拥有一个唯一的原型。
<scripttype="text/javascript">function Person(){ //大写,代表构造函数
Person.prototype.name = "aaaa";//原型属性
Person.prototype.age = "21";
Person.prototype.run = function()//原型方法
{
returnthis.name + this.age + 'studying';
}
}
var p1= new Person();
var p2 = new Person();
alert(p1.constructor);//构造属性,可以获取构造函数本身,//作用是被原型指针定位,然后得到构造函数本身</script>
__proto__
属性和prototype属性的区别
prototype
是function
对象中专有的属性。__proto__
是普通对象的隐式属性,在new的时候,会指向prototype
所指的对象;__ptoto__
实际上是某个实体对象的属性,而prototype
则是属于构造函数的属性。__ptoto__
只能在学习或调试的环境下使用。
原型模式的执行流程
1.先查找构造函数实例里的属性或方法,如果有,就立即返回。
2.如果构造函数的实例没有,就去它的原型对象里找,如果有,就立即返回
原型对象的
<scripttype="text/javascript">
function Box(){ //大写,代表构造函数
Box.prototype.name = "aaaa";//原型属性
Box.prototype.age = "21";
Box.prototype.run = function()//原型方法
{
returnthis.name + this.age + 'studying';
}
}
var box1 = new Box()
var box1 = new Box();
alert(box1.name);//aaaa,原型里的值
box1.name = "bbbb";
alert(box1.name);//bbbb,就近原则var box2 = new Box();
alert(box2.name);//aaaa,原型的值,没有被box1修改</script>
构造函数.prototype = 原型对象
原型对象.constructor = 构造函数(模板)
原型对象.isPrototypeof(实例对象) 判断实例对象的原型 是不是当前对象
javascript语言里任何匿名函数都是属于window对象,它们也都是在全局作用域构造时候完成定义和赋值
<script type="text/javascript"> function ftn03(){
var ftn04 = function(){
console.log(this);// window };
ftn04();
}
ftn03();
</script>
构造函数方式
function person(name,age){
//在执行第一行代码前,JS引擎会生成一个对象
this.name = name:
this.age = age;
this.getInfo = function(){
alert(this.name);
}
//此处有一个隐藏的return语句,用于将之前生成的对象返回
}
var p = new person('a',11)