对象:由多组无序属性组成的数据结构 (键值对) 成对出现:属性名 属性值
字面量 简单对象也存在构造函数 (如:下面的dog其构造函数是Objecd 数值Number ⋯⋯)
var dog = {name:"tom",age:2};
构造函数 批量创建同类对象
function Dog(name,age){this.name = name; this.age = age;}
对象的属性名是单例的 所以属性值单例(成对出现)
[如果创建多个同名属性对应着属性值,值/地址存在栈中 1.基本数据类型存的具体值 属性名指向它 你再来一个同名的属性名、还是本来的属性名 所以还指向原来的值 现在你把指向的值变了 现在的值就替换了原来的值)所以属性名是单例、多例的话之前的也会被覆盖掉,同样也解释了DOM0级事件只支持一个同名事件名的处理程序(oDiv.onclick=function(){} 属性名=属性值);
由于dom0 事件处理本质上是对象属性的赋值操作,由于数值值唯一的特点。所以dom0方式只能为dom对象绑定一个有效的事件处理函数。2.引用数据类型存的是地址 属性名指向地址(值在堆中 同上),如果 字面量 new 会在堆中重新开辟空间]
原型:(构造函数具有prototype属性) 函数对象通常具有一个prototype的属性叫做原型属性
原型属性中的所有属性可以为其创建的对象共用
实例:构造函数创建的对象 相对于 构造函数 叫构造函数的实例
每个对象都有一个proto属性 指向其构造函数的原型
js中没有继承,但可以通过构造函数的原型属性 来搭建继承 原型继承
继承:上级函数的实例a赋值给下级函数的原型、下级函数的实例就可指向这个实例a (这个实例a是现在下级函数的原型)
function Dog(name){ this.name = name; }
Dog.prototype.say = function(){ console.log("wangwang" );}
var d = new Dog("tom");
d.proto 指向函数原型 原型谁创建的、底层的 Object对象创建的 所以输出Object{}
d实例是Dog对象创建的 打印d 输出Dog{}
注意:下级函数要先继承 后创建对象(实例) [如果后继承:下级函数的实例指向的原型是下级函数原来的原型,只要继承原型就改变了,所以在继承前访问原型中的属性访问不到]
存在弊端:上级函数实例a赋值给下级函数,实例a的私有属性、共有属性(下级要的)都给了下级函数原型中(原型继承无法解决私有属性构建逻辑的复用) 逻辑指属性
原型方式的继承不能实现多继承,但可以多级继承,因为原型继承的本质就是属性赋值。属性值单例的
(stu.proto.proto.proto.proto null)
原型链:构造函数原型通过函数之间原型继承,逐级链接,组成链型结构
多继承: 借用构造函数的继承,解决了私有属性初始化逻辑的复用(使用call、apply借用上级私有属性初始化逻辑,初始化逻辑就是下级属性的初始化)
借用构造函数方式的继承: 通过call apply 函数名.call(要替换的对象名/this指向的对象,函数的实参) 看的是构造函数
组合继承:原型继承与多继承放在一起 (两者互不影响)
寄生方式继承:1.创建一个过渡函数 使上级函数的原型代替过渡函数的原型
(tmpFn.prototype = Car.prototype);
[原型是底层创建的原有的 Objecd 谁(上级)创建原型、原型中有个属性constructor(指向下级函数);所以没有了它会隔级找]
2.然后 创建多度函数的实例a 把实例a赋值给下级函数的原型
因为constructor(指向函数) 是原型中的属性所以实例本身没有constructor、在原型里(proto里,proto指向原型);所以把实例a赋值给下级函数的原型时 只有proto,constructor没有,要手动添加上(不然在指向函数时会隔级找)
Bike.prototype.constructor = Bike;