JS高级--面向对象

一、对象定义的三种方式

一、对象的构成、

对象是由它本身和它的原型公共构成的, 对象的原型是 proto (也是一个对象)

二、原型链:

对象或构造函数由本身和原型构成,对象或构造函数也是一个对象,由本身和原型构成,这样一直往后沿深,形成原型链。

二、定义对象键和键值

分为直接定义、追加定义

var obj2 = new Object();
// 添加对像内容
obj2.name = "张三";
obj2.age = 20;
console.log(obj2);
// 覆盖定义 obj2对象
obj2 = {
    height:"178cm",
    hobby:function(){
        console.log("喜欢篮球");
    }
}
console.log(obj2);

三、对象和JSON之间的转换

JSON键名一定要加 "",键值没有函数,规范 :引号使用--外单内双
 var JSON = '{"name":"张三","age":"19"}';

var json1 = JSON.stringify(obj2);   // 对象转json串(字符串化)
var newObj = JSON.parse(json1);     // json数据转换成对象(解析)


四、传值和传址问题

1、传值,

var a = 10;
var b = a;
b = 5;
console.log(a,b); // 10 5 。不会相互影响

2、传址

var obj1 = {
    a:10
}
var obj2 = obj1;
obj2.a = 5;
console.log(obj1.a,obj2.a);  // 5 5

// 数组传址,数组之间相互影响
var arr1 = [1,2,3,4,5];
var arr2 = arr1;
arr2[1] = 10;
console.log(arr1[1]);        // 10

解决传址问题:

1、深拷贝 -- 将数组转为JSON串,再转为数组

var arr1 = [1,2,3,4,5];
var arr2 = JSON.parse(JSON.stringify(arr1));
arr2[1] = 10;
console.log(arr1);         // 2

2、使用空的构造函数,作为两个函数原型的桥梁。

解决方案: 空的构造函数,作为父级、子级的传递桥梁。

function People(sex,eat){
    this.sex = sex;
    this.eat = eat;
}
People.prototype.actions = () => {
    console.log('People === actionsFn')
}

function Student(sex,eat){
    this.sex = sex;
    this.eat = eat;
}
Student.prototype.actions = () => {
    console.log('Student === actions')
}

------------------------------
 Student.prototype = People.prototype;
------------------------------


++++++++++++++++++++++++++++++
function Link(){
    Link.prototype = People.prototype;
    
}
Student.prototype = new Link;
+++++++++++++++++++++++++++++++


Student.prototype.actions = () => {
    console.log('Stundent === New');
}

const newPeo = new People('女','水果');
const newStu = new Student('man','dontknow');
newPeo.actions();
newStu.actions();


五、构造函数

构造函数(类似类的概念); 约定俗成:首字母大写

1、定义构造函数
function People(eat,age){
    this.eat = eat;
    this.age = age;
    this.action = function(){
        console.log("吃饭,睡觉");
    }
}
2、构造函数的原型
  • 构造函数由本身和原型prototype构成;
  • 原型链:原型是一个构造函数,又由本身和构造函数构成,一直往后延深,形成原型链。
  • 一般属性写在构造函数里,方法写在原型上,目的是:便于维护
  • 在写方法时,直接:People.prototype = function({}),会覆盖原有的原型
    People.prototype.action = function(){
        console.log(this);  // 实列化是谁,this指向谁。
        console.log(this.eat);
        console.log("我是爸爸");
    }
3、通过原型找构造函数
console.log(People.prototype.constructor);
4、调用构造函数

关键字 new:实列化构造函数。抽象具体化,将类变为对象

newPeople = new People("米饭",18);
console.log(newPeople.eat);
newPeople.action();
5、关键字new具体做的三件事:

创建空的对象

 var newPeople = new Object();

将构造函数的this指向改变成空对象 (3种写法:call/apply/bind)

People.call(newPeople,"米饭",18);  
//  People.apply(obj,["米饭",18])  
//  People.bind(obj)("米饭",18);

将构造函数的原型赋给对象原型

 newPeople.__proto__ = People.prototype;  // 构造函数的原型 赋给 实列化原型
6、构造函数的原型
console.log(People.prototype === newPeople.__proto__);  // true , 只是表现形式不一样
7、构造函数的 -- 继承

1、改变this指向

function Father(eat,age){
    this.eat = eat;
    this.age = age;
    this.fath = function(){
        console.log("我是爸爸");
    }
}
function Sons(eat,age){
    Father.call(this,eat,age);
    this.sonFn = function(){
        console.log("我是儿子");
    }
}

2、原型的继承

// 不可以直接:Sons.prototype = father.prototype;
// -- 解决传址问题 !!!
    // 1、定义一个空构造函数,其原型指向father原型,son原型指向其原型

function Center(){};
Center.prototype = Father.prototype;
Sons.prototype = new Center();  // 空构造函数只有原型

Father.prototype.typeFn = function(){
    console.log("父级重写");
}
Sons.prototype.typeFn = function(){
    console.log("子级重写");
}
var newSons = new Sons("苹果",10);
var newFather = new Father("苹果",10);
console.log(newSons.eat);
newSons.sonFn();
newSons.fath();

newFather.typeFn();
newSons.typeFn();

六、类的特性:封装、继承、多态、重载; [js:封装、继承]

1、封装 -- 公有、私有属性
function Person3(name){
    // 1.1、私有属性
    var name = name;
    // 1.2、公有属性
    this.height = "179cm";
    // 1.3、get方法:通过公有方法,访问私有属性
    this.get = function(){
        return name;
    }
    // 1.4 set方法:设置私有属性
    this.set = function(newname){
        name = newname;
        console.log(name);
    }
}
newPerson3 = new Person3("三三");
console.log(newPerson3.name);  // undefind:作用域问题,访问不到。只能在构造函数内部访问
console.log(newPerson3.get());  // 三三
 newPerson3.set("四四");         // 四四
2、继承

1、利用 apply、call、bind 方法,改变this指向 实现继承

  • 通过 apply、call、bind:继承父类 的 this ----> 只能继承实例的 方法、对象
  • 父类公有对象、方法 都通过 this 递增,每 new 一个 实例都导致 this 内容的存储,耗费很大内存
function Student(name, age, grade){

    // 将 this 指向 Person,达到继承 Person对象实例 的 方法、目的
    Person.apply(this, arguments);  
    // Person.call(this, arguments);
    // Person.bind(this)(arguments);
    this.grade = grade;
}

function Person(name, age){
    this.age = age;
    this.name = name;
    this.type = 'person';
}
Person.prototype.proFn = () => {
    console.log('Person === proFn')
}

var student = new Student('sname', 'sage', 'sgrade');
console.log(student);



2、空对象作为中介

  • 只能通过 Prototype 来传递
  • 优势:
    少 new 很多的 this 构造函数,节省内存
    子类 prototype 改变,不影响父类
function Student(name , age, grade){
    this.grade = grade;
}
function Person(name, age){
    this.name = name;
    this.age = age;
}
Person.prototype.type = 'preson';

function Extend(Child, Partent){
    var F = function(){};                // 空对象
    F.prototype = Partent.prototype;    
    Child.prototype = new F();
    Child.prototype.constructor = Child; // 将 Child 赋给 当前对象的构造函数 ( 防止继承链的紊乱,需手动把构造器指回Child )
    Child.uber = Partent.prototype;      // Child 的 Uber 属性,直接指向 Partent 的 prototype (只是为了实现继承的完备性,纯属备用性质)
}

Extend(Student, Person);
var student = new Student('sname', 'sage', 'sgrade');
Student.prototype.subType = 'ssubType';
console.log('student +++', student.type)
console.log('student +++', student.subType)

3、拷贝继承

    function Student(name, age, grade){
        this.grade = grade;
    }
    function Person(name, age){
        this.name = name;
        this.age = age;
    }
    function Extend(Child, Partent){
        var p = Partent.prototype;
        var c = Child.prototype;
        for (const i in p) {          // 遍历拷贝赋值
            c[i] = p[i];
        }
        c.uber = p;
    }
    Person.prototype.type = 'person';
    Extend(Student, Person);

    Student.prototype.subType = 'sperson';
    var student = new Student('sname', 'sage', 'sgrade');
    console.log(student)

七、工厂模式

function Factory(height){
    //obj人类
    var obj = {};
    obj.name = 20;
    obj.name = "张三";
    obj.height = height;
    obj.hobby = function(){
        console.log("我喜欢篮球");
    }
    return obj;
}
var newFactory = Factory("162");
console.log(newFactory.height);
newFactory.hobby();

你可能感兴趣的:(JS高级--面向对象)