构造函数(Constructor)
构造函数就是类。构造函数首字母大写,这是规范。
内部使用了this变量,对构造函数使用new运算符,就能生成实例对象。
function CreateCar(color,wheel){//构造函数首字母大写
//不需要自己创建对象了
this.color = color;//添加属性,this指向构造函数的实例对象
this.wheel = wheel;//添加属性/
}
//实例化
var cat1 = new CreateCar("红色","4");
var cat2 = new CreateCar("蓝色","4");
alert(cat1.color);//红色
alert(cat1.constructor == CreateCar); //true
alert(cat2.constructor == CreateCar); //true
Prototype 原型
每一个构造函数都有一个prototype属性,指向另一个对象。这个对象的所有属性和方法,都会被构造函数的实例继承。__proto__
是原型链,指向实例化的函数原型。
//showWheel都是一模一样的内容,每一次生成一个实例,都必须生成重复的内容,多占用一些内存。
function CreateCar(color,wheel){
this.color = color;
this.wheel = wheel;
this.showWheel = function(){//添加一个新方法
alert(this.wheel);
}
}
//还是采用同样的方法,生成实例:
var cat1 = new CreateCar("红色","4");
var cat2 = new CreateCar("蓝色","4");
alert(cat1.showWheel == cat2.showWheel); //false
//这时所有实例的showWheel属性和showName方法,其实都是同一个内存地址,指向prototype对象,因此就提高了运行效率。
function CreateCar(color,wheel){
this.color = color;
this.wheel = wheel;
}
//方法写原型里面
CreateCar.prototype.showWheel = function(){
alert(this.wheel);
}
CreateCar.prototype.showName = function(){
alert('车');
}
//生成实例。
var cat1 = new CreateCar("红色","4");
var cat2 = new CreateCar("蓝色","4");
cat1.showName();//'车'
alert(cat1.showWheel == cat2.showWheel );//true
alert(cat1.showName == cat2.showName );//true
console.log(cat1.__proto__ === CreateCar.prototype); //true
对象和函数的关系
对象是由函数构造出来的。
//Object是Function 的一个实例。
Object.constructor == Function //true
//函数是Function 的实例,但不是Object 的实例。
function fn(){}
fn.constructor == Function //true
fn.constructor == Object //false
//{} 与 Object 的关系
var obj = {};
obj.constructor === Object //true
静态方法和静态属性
只属于类而不属于实例化对象
function foo(){
this.show = function(){
return this;
}
}
foo.test = 123; //静态属性
//静态方法
foo.say = function(){
return this;
}
foo.say();//指向 foo 方法
var fn = new foo(); //实例化的新的对象,this指向这个新的对象,不能访问类的静态方法
fn.test;//undefined
fn.say(); //Noname1.html:45 Uncaught TypeError: fn.say is not a function
对象继承
//人类
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.run = function(){
console.log('跑路~')
};
Person.prototype.say = function(){
console.log('说话~')
};
console.log(Person.prototype);
//男人
function Man(){
this.sex = "男";
}
Man.prototype = Person.prototype;
Man.prototype.yyy = function(){
console.log('嘤嘤嘤');
}
//会发现Person的prototype也改变了,因为复杂对象的赋值操作是引用而不是赋值
console.log(Person.prototype);
Man.prototype == Person.prototype;//true
for in继承
//人类
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.run = function(){
console.log('跑路~')
};
Person.prototype.say = function(){
console.log('说话~')
};
console.log(Person.prototype);
//男人
function Man(){
this.sex = "男";
}
for(var key in Person.prototype){
Man.prototype[key] = Person.prototype[key];
console.log(key)
}
Man.prototype.yyy = function(){
console.log('嘤嘤嘤');
}
console.log(Person.prototype);//对象run、对象say
console.log(Person.Man);//对象run、对象say、对象yyy
采用中介继承
function ClassA(name){
this.name = name;
}
ClassA.prototype.say = function(){
console.log(666);
}
//中继来做准备工作
function Ready(){}//
Ready.prototype = ClassA.prototype;//引用
//需要来继承ClassA
function ClassB(){}
ClassB.prototype = new Ready();//new 返回了一个新对象 __proto__指向被实例化的构造函数的prototype
ClassB.prototype.constructor = ClassB;
console.log(ClassB.prototype);
采用中介,使用call改变this指向
function ClassA(name){
this.name = name;
}
ClassA.prototype.showName = function(){
console.log(this.name);
}
//中继来做准备工作
function Ready(){}//
Ready.prototype = ClassA.prototype;//引用
//需要来继承ClassA
function ClassB(name){
ClassA.call(this,name);
}
ClassB.prototype = new Ready();//new 返回了一个新对象 __proto__指向被实例化的构造函数的prototype
ClassB.prototype.constructor = ClassB;
console.log(ClassB.prototype);
var xiaoming = new ClassB('小明');
xiaoming.showName();
多态
同一个方法,面对不同的对象有不同的表现形式就叫做多态。
var obj = {
eat : function(_type){
if(_type == '猫'){
console.log('猫粮')
}else if (_type == "狗") {
console.log('狗粮')
}else{
console.log("吃饭");
}
}
};
obj.eat("狗");
hasOwnProperty
查看该属性是否在这个对象本身上,只有在自身属性上才会返回真,在原型链上会返回假。
function ClassA(){}
ClassA.prototype.test = function(){
console.log('test')
}
var a = new ClassA();
a.test();
console.log(a.hasOwnProperty('test')); //false
描述符(修饰符)
描述符是对一个属性的特性的描述,defineProperty设置描述符(修饰符),value设置属性值,configurable是否允许修饰符被改变 默认为false,enumerable 是否可以被枚举 默认为false,writable是否可以被 = 等号改变 默认为false。
var obj = {
a : 1
};
var c = 666;
Object.defineProperty(obj,'c',{
//value : 233,
//enumerable : false,
//writable : true,//他的值能否改变
//设置的时候调用
set : function(n){
//n 就是等号的右边的值
c = c*n;
},
//获取的时候调用
get : function(){
return c;
},
configurable : true,//是否可以再次修改修饰符
});