面向对象(一)

124 阅读3分钟

对象创建

1.字面量方式

let str = 'name';

let obj = {
    [str]:"张三",
    age:"20",
    hobby:function(){
        console.log("喜欢篮球")
    }
}

2.构造函数

let obj = new Object();
obj.name = "张三";
obj.age  = 20;
obj.hobby = function(){
    console.log("喜欢篮球")
}
console.log(obj);

3. Object.create() ;属性方法放在原型上;

let obj = Object.create({
    name:"张三",
    age:20,
    hobby(){
        console.log("喜欢篮球");
    }
})

4. 对象的调用

// 对象的调用;
console.log(obj.name);
console.log(obj['name']);

obj.hobby();

let str = "name";
console.log( obj.str); // undefined
console.log( obj[str]);

工厂模式

let zhangsan = {
    name:"张三",
    age:20,
    hobby(){
        console.log("喜欢篮球");
    }
}
let lisi = {
    name:"李四",
    age:21,
    hobby(){
        console.log("喜欢足球");
    }
}



// 工厂模式 :类
// 提高代码复用性
function Person(name,age,hobby){
    let obj = {};  // 添加原料
    obj.name = name;
    obj.age = age;
    obj.hobby = function(){
        console.log(hobby);
    }
    // 加工原料
    return obj; // 出厂;
}

let zhangsan  = Person("张三",20,"喜欢篮球");
let lisi  = Person("李四",21,"喜欢足球");
console.log(zhangsan);
console.log(lisi);

new

创建字符串

// let str = "";
// let str = new String();

new 执行函数时的特征

  • 执行函数
function test(){
    console.log("test");
}
test();
new test(); // 需要传参时加括号
new test;

  • 自动创建一个空对象
  • 把空对象和this绑定
  • 如果没有返回,会隐式返回this
function Test(){
    // let obj = {};  === this;


    // return this;
}

new Test();
这里是工厂模式的简化:
原工厂模式
function Person(name,age,hobby){
    let obj = {};  // 添加原料
    obj.name = name;
    obj.age = age;
    obj.hobby = function(){
        console.log(hobby);
    }
    // 加工原料
    return obj; // 出厂;
}
简化后(构造函数)
// 工厂模式;
function Person(name,age,hobby){
    // 手动创建空对象可以注释掉,new 运算符会帮我们做
    // 把空对象和this绑定
    // let obj = {}; // 添加原料  === this;
    
    // 加工原料
    this.name = name;
    this.age = age;
    this.hobby = function(){
        console.log(hobby);
    }
    
    // 如果没有返回,会隐式返回this
    // this 相当于 obj
    // return obj; //出厂;
}

let zhangsan =  new Person("张三",20,"篮球");
console.log( zhangsan.name);
zhangsan.hobby();

构造函数

// 构造函数;1.首字母大写(约定俗成,与普通函数区分);2.this指向实例化对象;
function Person(name){
    //注意:: name,age,hobby 都是跟实例化对象有关系的,属于zhangsan
    this.name = name;
    this.age =20;
    this.hobby = function(){
        console.log("喜欢篮球");
    }
}

// new  : 实例化;
let zhangsan  = new Person("张三");

统计实例化的次数

function Person(name){
    this.num = 0;
    this.name = name;
    this.age =20;
    this.hobby = function(){
        console.log("喜欢篮球");
    }
}
let zhangsan  = new Person("张三");
zhangsan.num ++;
console.log(zhangsan.num);

let lisi  = new Person("李四");
lisi.num ++;
console.log(lisi.num);

类的属性,静态属性和方法
function Person(name){
    // this.num = 0;
    this.name = name;
    this.age =20;
    this.hobby = function(){
        console.log("喜欢篮球");
    }
}
// 静态成员;
// 静态属性和方法;(属于类本身的);
Person.num = 0;
Person.fn = function(){
    console.log("fn");
}
// new  : 实例化;
let zhangsan  = new Person("张三");
Person.num++

let lisi  = new Person("李四");
Person.num++
console.log(Person.num);

构造函数的性能问题

hobby本身一个对象,比较的时候,不仅值要一样,在内存中的地址也要一样。两次实例化相对于开辟了不同的地址。100个人就会有100个地址,消耗内存。
function Person(name){
    this.name = name;
    this.age = 20;
    this.hobby = function(){
        console.log("喜欢篮球");
    }
}

let zhangsan = new Person("张三");
let lisi = new Person("李四");

console.log(zhangsan.hobby===lisi.hobby);

原型

每个构造函数实例化的过程中,都会有两部分构成:构造函数 + 公共空间——原型
构造函数每次实例化的过程中,在内存中会去开辟新的地址
prototype 在内存中都是公共的空间,节约内存。每次声明构造函数的时候,会自动声明一个原型,原型中的this也是指向实例化对象
function Person(name){
    this.name = name;
    this.age = 20;
    // this.hobby = function(){
    //     console.log("喜欢篮球");
    // }
}

// 公共空间原型;
Person.prototype.hobby = function(){
    console.log("喜欢篮球");
}

let zhangsan = new Person("张三");
let lisi = new Person("李四");

console.log(zhangsan.hobby===lisi.hobby);

function Person(name){
    this.name = name;
    this.age = 20;
}

// 公共空间原型;
Person.prototype.hobby = function(){
    console.log("喜欢篮球");
}

let zhangsan = new Person("张三");
// 得到zhangsan 对象,对象由两部分构成:自身的属性跟方法 + 自身的原型__proto__

console.log(zhangsan.__proto__ )
console.log(Person.prototype)
console.log(zhangsan.__proto__===Person.prototype);
// zhangsan.__proto__, Person.prototype 表现形式不同,其实是一个东西
let lisi = new Person("李四");

constructor

function Person(name){
    this.name = name;
    this.age = 20;
}

// 功能空间原型;
Person.prototype.hobby = function(){
    console.log("喜欢篮球");
}

// 原型的固有属性;
console.log( Person.prototype.constructor===Person);

let zhangsan = new Person("张三");
console.log(zhangsan.constructor===Person);
console.log(zhangsan);

勿在原型中覆盖属性

function Person(name){
    this.name = name;
    this.age = 20;
}


// 采用追加的方式可行
// Person.prototype.hobby = function(){
//    console.log("喜欢篮球");
// }

// 这种写法会覆盖掉constructor
Person.prototype = {
    hobby:function(){
        console.log("hobby");
    }
}

let zhangsan = new Person("张三");
console.log(zhangsan.constructor===Person);

function Person(name){
    this.name = name;
    this.age = 20;
}

// 该写法需要自己加上constructor
// constructor 实例化对象是通过哪个构造函数来进行实例的
Person.prototype = {
    constructor:Person,
    hobby:function(){
        console.log("hobby");
    }
}

let zhangsan = new Person("张三");
console.log(zhangsan.constructor===Person);

判断类型

let str = new String("abd");
// let str = "abc";
console.log(str.constructor===String);