function Test(){};
var f1=new Test();
test()是一个构造函数。引申:构造函数与普通函数:
构造函数:1.用new关键字调用;2.函数内部可以使用this关键字;3.一般不使用return;4.函数名首字母大写
普通函数:不需要使用new关键字调用;2.函数内部不建议使用this;3.可以使用return;4.函数首字母小写
比如:
window.onload = function (a,b) {
/*1.普通函数实现加法*/
var myMath1=function(a,b){
return(a+b)
}
console.log(myMath1(1,2))//打印出3
/*2.构造函数实现加法*/
//创建一个构造函数,并通过参数来获取该构造函数的变量。
var MyMath2=function (a,b){
this.a=a;
this.b=b;
}
//通过函数的prototype来自定义一个sum方法
MyMath2.prototype.sum=function(){
return this.a+this.b;
}
//实例化一个对象
var test=new MyMath2(1,2);
//调用该对象的sum方法
console.log(test.sum())//打印出3
}
下面我们实现一个最简单的原型,让两个实例化对象共享一个类的方法。
var Father = function (health) {
this.health = health;
}
Father.prototype.getHealth = function () {
console.log(this.health);
}
var father1 = new Father("good");
var father2 = new Father("very good");
father1.getHealth();//打印good
father2.getHealth();//打印very good
下面我们来实现一个原型链,让子类继承父类的属性。
var Father = function () {
this.health = "very good";
}
Father.prototype.getHealth = function () {
console.log(this.health);
}
var Son = function () {
//继承父类属性
Father.call(this);
}
var son=new Son();
console.log(son.health);//打印very good
console.log(son.getHealth);//打印undefined
可以看出,子类继承父类的属性可以,继承方法就是undefined,那么下面我们再实现一个原型链,让子类继承父类的方法。
var Father = function () {
this.health = "very good";
}
Father.prototype.getHealth = function () {
console.log(this.health);
}
var Son = function () {}
//继承父类方法
Son.prototype = new Father();
var son=new Son();
son.getHealth();//打印very good
console.log(son.health);//打印very good
最后,我们通过ES6的新方法来实现原型的封装,原型链中子类对父类的方法和属性的基础。
//(1)简单原型
class Father {
constructor(health) {
this.health = health
}
//也可写成getHealth=function(){},下面这种函数的写法是ES6的新写法
getHealth() {
console.log(this.health);
}
}
var father1 = new Father("good");
var father2 = new Father("very good");
father1.getHealth();//打印good
father2.getHealth();//打印very good
//(2)原型链子类继承父类属性和方法
class Father {
constructor() {
this.health = "good"
}
getHealth() {
console.log(this.health);
}
}
//子类继承父类的写法,跟C++有点像似
class Son extends Father{
constructor(){
//super在子类中必须要使用一次
super()
}
}
var son=new Son();
//可以发现,这种写法子类继承了父类的属性和方法
console.log(son.health);//打印good
son.getHealth();//打印good
1.__proto__和constructor属性是对象独有的;prototype属性是函数独有的;由于函数也是一种对象,所以函数具有这三种属性;
2.__proto__的作用是访问一个对象的属性时,若该对象没有此属性,就会找它的__proto__属性所指向的父对象继续找,直到找到终点null,然后返回undefined,这就是原型链。
3.prototype属性的作用是让该函数所实例化的对象都可以访问到公共的属性和方法,即f1.__proto__==test.prototype。
4.constructor的作用是指向该对象的构造函数,每个对象都含有构造函数,而function的构造函数就是它本身。
5.JS中有一句“万物皆对象”,主要是指基本类型数据里面也含有__proto__属性,比如var str1="ss";console.log(str1.__proto__)打印一个String对象。在JS中,string、number、boolean类型都可以打印出它的__proto__属性,null打印不出,但是console.log(typeof null)却打印出一个object。所以说“万物皆对象”这句话也有一定的道理。注意的是:var str1=String("ss"),var str2="ss",var str3=new String("ss"),str1==str2,str1!=str3,因为str1和str2都是string类型的,而str3属于object类型的。基本数据类型只是一个值,单独开辟一个内存空间,存储在栈内存中,而引用数据类型包含了值和地址,存储在一个堆内存中。