对象
javascript对象书写样式
var obj = {
属性:属性值
函数名:函数
数组名:数组
}
var obj ={
name:"sofency",
sayHello:function(){
alert("hello sofency")
},
interest:["basketball","football","table"]
}
对象如何进行调用其中的成员哪
通过.
运算符
eg: console.log(obj.name); console.log(obj.sayHello());
对象成员的增删改查
增 直接在对象名后面用.
运算符添加成员 obj.age=20
;
删 使用delete关键字进行删除成员 eg : delete obj.name
;
改 直接修改 eg : obj.sayHello=function(){alert("hello alice")}
;
查 使用.
运算符 eg: obj.name
;
上述属于直接单独构造一个obj,其中的属性和功能都是定制的,那么我们能否创建一个工厂进行批量化生产对象,此时我们该如何构造工厂也就是java中的类哪 ,示例如下
我们将人进行抽象化
// 示例1
function Person(name,age,interest){
this.name = name;
this.age = age;
this.interest = interest;
this.sayHello= funtion(){
alert("hello "+ this.name);
}
}
// 生产人
var person1 = new Person("sofency",18,["basketball","football","baseball"]);
//这就生产一个对象了
//上述创建你是否有疑问,对于从java转来学前端的对于上述创建应该先声明变量再使用`this.属性`,但是这就是js添加属性方便的原因,想想js是如何给对象添加成员的,疑问也就解决了
原型 prototype
对于上述构造函数来说假如我们有这样的需求,我们知道我们创几件的构造函数都是软件工程专业的,于是有了这样的工厂
//示例2
function Person(name,age,interest){
this.name = name;
this.age = age;
this.major = "software";
this.interest = interest;
this.sayHello= function(){
alert("hello "+ this.name);
}
}
问题:
同时暴露出这样一个问题 我们再生产学生对象时每次new构造器时都要进行创建major成员,无疑是降低了效率,于是js提供了原型的概念
我们在使用示例1
的构造器时,在构造器外面写上这样的代码 Person.prototype.major="software"
;
这样我们在创建的任何对象中都有major成员,即构造器名.prototype
中的成员,其所创建的对象都可以使用,而且如果prototype
中的成员发生改变,对象中的该成员也会实时的发生改变。
这就是原型的魅力所在,还有对于js的原型链结构图如下
从图中我们得到什么信息
- js是通过函数来模拟类
- 对象具有属性__proto__,可称为隐式原型,一个对象的隐式原型指向构造该对象的构造函数的原型,这也保证了实例能够访问在构造函数原型中定义的属性和方法
自定义函数,每创建一个函数 js就会给该函数创建一个原型 这就解释了为什么所有的对象都有`major`成员了
function Foo(){}
自定义对象
var foo = new Foo();
foo.__proto__ === Foo.prototype;//true
- 对象如何查找成员
b
的 是通过原型链的方式进行查找的,首先先查找自己原有的成员,如果没有找到则沿着原型链找自定义函数原型(构造器.prototype
)中的成员,直到找到原型链顶端或者找到为止; - 如果遇到下面情况
function test(name,age){
this.name = name;
this.age= age;
}
test.prototype.name ="alice";
var test1 = new test("sofency",18);
console.log(test1.name);// 会是谁
//答案是sofency 就好比找一个钉子,在家就找到了,就没必要在到超市去买了
当我们发现两个对象的特征一样时,如何进行对象的复制 使用Object.create()方法
var person3 = Object.create(person1);
当然person3也能找到person1原型链上所有的东西,随着原型链的改变而实时发生改变
对象的继承
- 第一种情况
function Person(name,age,interest){
this.name = name;
this.age = age ;
this.interest = interest;
this.sayHello = function(){
alert("hello "+ this.name);
}
}
对于老师构造器 使用call方法进行`伪继承`
function Teacher(name,age,interest,grade){
//调用 call 方法
Person.call(this,name,age,interest);//借鸡生蛋 借用Person的工厂再将生产的主人指向自己 就是自己生产的
this.eat = function(){
alert("hello world");
}
}
严格的来说 这不算继承,这只是想当与把Person中的代码再拿到Teacher中执行一遍,工作量还是那么重,于是有了圣杯模式
圣杯模式实现继承
function Person(name,age,interest){
this.name = name;
this.age = age ;
this.interest = interest;
this.sayHello = function(){
alert("hello "+ this.name);
}
}
上面使用call方法仅限于继承一些自己的属性 对于prototype中的方法无法继承请看下面的图
Person.prototype.teach= function(){alert("我们上课了")}
function Teacher(name,age,interest,grade){
//调用 call 方法
Person.call(this,name,age,interest);
this.eat = function(){
alert("hello world");
}
}
我们现在想让Teacher也具有Person中的teach功能,我们该怎么办
var inherit = funnction(son,father){
son.prototype = Object.create(father.prototype);//孩子的原型指向新创建的与父亲一样的原型对象
但是此时son.prototype.constructor 指向的是father的构造器
son.prototype.constructor = son;
}
inherit(Teacher,Person);
不使用圣杯模式
// 使用圣杯模式后