1.构造函数(一般函数名首字母大写)
function Person(name,age,job){
this.name = name;
this.age = age;
this.sayName = function(){console.log(this.name)}
}
var person01 = new Person('Alice',22);
var person02 = new Person('Lili',21);
上面的例子中person1和person2都是Person的实例。这两个实例都有一个construtor属性,改属性指向Person
实例的构造函数属性(constructor)指向构造函数。
2.原型对象
在javascript语言是一种面向对象语言,但是他不想其他语言有''子类''和 ''父类''的概念,里面所有的数据类型都是对象。这些对象需要我们将对象聚集起来就需要用到原型对象。
并且我们通过构造函数实例化出来的对象,都是复制构造函数的属性,因此每一个对象都有属于他自己的内容,与父类构造函数没有关系。这里就有一个问题:每个实例化出来的对象在继承构造函数中的属性,存在完全一模一样的,比如构造一个学生函数,每个学生都得上学下学这个行为属性,如果我们将每个实例化对象都写入这些相同的属性会造成大量的资源浪费。我们可以将这些共有属性存放在一个地方,减少占用内存的呢?通过原型对象就能做到。
在JavaScript中,每当定义一个对象(函数也是对象)时候,对象中都会包含一些预定义的属性。其中每个函数对象都有一个prototype属性,这个属性指向函数的原型对象。
每个对象都有__proto__属性,只有函数对象才有prototype属性。
原型对象就是一个普通的对象。
function Person() {
}
Person.prototype.name = 'a';
Person.prototype.age = 22;
Person.prototype.sayName = function(){console.log(this.name)};
var person01 = new Person();
person01.sayName(); //a
var person02 = new Person();
person02.sayName(); //a
console.log(person01.sayName == person02.sayName); //true
其实原型对象就是普通的对象,可以将上面的例子改写一下就比较明白了:
Person.prototype = {
name: 'a',
age: 22,
job: 'Software Engineer',
sayName: function() {
console.log(this.name);
}
}
在默认情况下,所有的原型对象都会自动获得一个constructor属性(构造函数),这个属性执行prototype属性所在的函数。
在上面例子中person01的constructor指向的就是Person这个构造函数。Person构造函数的constructor指向Funtion内置对象。
在对象中可以通过delete删除属性,delete只能删除对象属性,不能删除变量和参数
3.原型链
3.1在js中是依靠原型链来实现继承的。拿作用域来对比:
作用域:保存着所有的变量
原型:保存着所有对象的属性和方法
作用域链:控制变量的使用顺序是 优先使用活动对象中的局部变量,局部变量中没有,就会沿着作用域向父级作用域查找。
原型链:控制对象访问成员的使用顺序:优先使用自己的,最近没有的,才沿着原型链向父级查找。
原型链的最顶端是Object.prototype;作用域链的终点是window。
简单概述:所有不需要对象访问的变量都保存在作用域链中;所有需要对象访问的变量都保存在原型链中。
3.2原型链中的三种属性:
proto:是对象的默认属性,每个对象都有。它指向原型对象
prototype:同样的也是指向原型对象,但是与proto不一样的是,只有构造函数才有这个属性。
constructor:每一个原型对象都有这个属性,指向构造函数(与prototype是成对的,相互的)。
原型链简图:
(自己画的图太丑了,估计也就自己能看懂,这个图是从网上下载的不过要表达的内容是一样的)