一
/*
1.在ES6之前如果定义一个类?
通过构造函数来定义一个类
*/
function Person(myName, myAge) { // 实例属性 // this.name = "lnj"; // this.age = 34; this.name = myName; this.age = myAge; // 实例方法 this.say = function () { console.log(this.name, this.age); } // 静态属性 Person.num = 666; // 静态方法 Person.run = function () { console.log("run"); } } // let p = new Person(); let p = new Person("zs", 18); p.say(); console.log(Person.num); Person.run();
/*
2.从ES6开始系统提供了一个名称叫做class的关键字, 这个关键字就是专门用于定义类的
*/
class Person{ // 当我们通过new创建对象的时候, 系统会自动调用constructor // constructor我们称之为构造函数 constructor(myName, myAge){ this.name = myName; this.age = myAge; } // 实例属性 // name = "lnj"; // age = 34; // 实例方法 say(){ console.log(this.name, this.age); } // 静态属性 static num = 666; // 静态方法 static run() { console.log("run"); } } // let p = new Person(); let p = new Person("zs", 18); p.say(); console.log(Person.num); Person.run();
需要注意的地方:
1
class Person{ // 以下定义"实例属性"的方式并不是ES6正式版标准中的写法, 大部分的浏览器不支持 // 在ES6标准中添加实例属性都需要在constructor中添加 // 实例属性 // name = "lnj"; // age = 34; constructor(){ this.name = "lnj"; this.age = 34; } // 实例方法 say(){ console.log(this.name, this.age); } } let p = new Person(); console.log(p);
2
class Person{ // 以下定义"静态属性"的方式并不是ES6正式版标准中的写法, 大部分的浏览器不支持 // 在ES标准中static只支持定义静态方法不支持定义静态变量 // 静态属性 // static num = 666; // 静态方法 static run() { console.log("run"); } } Person.num = 666; let p = new Person(); console.log(p);
二
function Person(myName, myAge) { // 实例属性 this.name = myName; this.age = myAge; // 实例方法 this.hi = function () { console.log("hi"); } } // 原型上的方法 Person.prototype.say = function () { console.log(this.name, this.age); } let p = new Person("lnj", 34); console.log(p); class Person{ constructor(myName, myAge){ this.name = myName; this.age = myAge; //构造函数里面添加的方法会添加到 对象本身 this.hi = function () { console.log("hi"); } } //在类里面添加的方法会加到原型对象中 say(){ console.log("hi"); } } let p = new Person("lnj", 34); console.log(p);
四
注意点:
如果通过class定义类, 那么不能自定义这个类的原型对象
如果想将属性和方法保存到原型中, 只能动态给原型对象添加属性和方法
function Person(myName, myAge) { // 实例属性 this.name = myName; this.age = myAge; // 实例方法 this.hi = function () { console.log("hi"); } } // 原型上的方法 // Person.prototype.type = "人"; // Person.prototype.say = function () { // console.log(this.name, this.age); // }; //function方式定义的构造函数可以修改 原型对象 Person.prototype = { constructor: Person, type: "人", say: function () { console.log(this.name, this.age); } }; class Person{ constructor(myName, myAge){ this.name = myName; this.age = myAge; this.hi = function () { console.log("hi"); } } run(){ console.log("run"); } } // Person.prototype.type = "人"; // Person.prototype.say = function () { // console.log(this.name, this.age); // }; let obj = { constructor: Person, type: "人", say: function () { console.log(this.name, this.age); } }; //修改对象原型无效 Person.prototype = obj; let p = new Person("lnj", 34); console.log(p);
五 继承
ES6之前的继承
1.在子类中通过call/apply方法借助父类的构造函数
2.将子类的原型对象设置为父类的实例对象
function Person(myName, myAge) { this.name = myName; this.age = myAge; } Person.prototype.say = function () { console.log(this.name, this.age); } function Student(myName, myAge, myScore) { // 1.在子类中通过call/apply方法借助父类的构造函数 Person.call(this, myName, myAge); this.score = myScore; this.study = function () { console.log("day day up"); } } // 2.将子类的原型对象设置为父类的实例对象 Student.prototype = new Person(); Student.prototype.constructor = Student; let stu = new Student("zs", 18, 99); stu.say();
1.在ES6中如何继承
1.1在子类后面添加extends并指定父类的名称
1.2在子类的constructor构造函数中通过super方法借助父类的构造函数
class Person{ constructor(myName, myAge){ // this = stu; this.name = myName; // stu.name = myName; this.age = myAge; // stu.age = myAge; } say(){ console.log(this.name, this.age); } } /* 1.在ES6中如何继承 1.1在子类后面添加extends并指定父类的名称 1.2在子类的constructor构造函数中通过super方法借助父类的构造函数 */ // 以下代码的含义: 告诉浏览器将来Student这个类需要继承于Person这个类 class Student extends Person{ constructor(myName, myAge, myScore){ // 1.在子类中通过call/apply方法借助父类的构造函数 // Person.call(this, myName, myAge); super(myName, myAge); this.score = myScore; } study(){ console.log("day day up"); } } let stu = new Student("zs", 18, 98); stu.say();
六 获取对象类型
let obj = new Object(); console.log(typeof obj); // object let arr = new Array(); /* * 这样的打印会是object,这是因为 在所有构造函数中,内部其实会新建一个Object对象,然后赋值给this * */ console.log(typeof arr); // object console.log(arr.constructor.name); // Array function Person() { // let obj = new Object(); // let this = obj; this.name = "lnj"; this.age = 34; this.say = function () { console.log(this.name, this.age); } // return this; } let p = new Person(); // console.log(typeof p); // object console.log(p.constructor.name); // Person
七 instanceof 关键字
1.什么是instanceof关键字?
instanceof用于判断 "对象" 是否是指定构造函数的 "实例"
2.instanceof注意点
只要 构造函数的原型对象出现在实例对象的原型链中都会返回true
class Person{ name = "lnj"; } let p = new Person(); console.log(p instanceof Person); // true class Cat{ name = "mm"; } let c = new Cat(); console.log(c instanceof Person); // false function Person(myName) { this.name = myName; } function Student(myName, myScore) { Person.call(this, myName); this.score = myScore; } Student.prototype = new Person(); Student.prototype.constructor = Student; let stu = new Student(); /* * 返回true的原因为 Person的原型对象出现在了stu的原型链上 * */ console.log(stu instanceof Person); // true
八 isPrototypeOf
1.什么是isPrototypeOf属性
isPrototypeOf用于判断 一个对象是否是另一个对象的原型
2.isPrototypeOf注意点
2.1只要调用者在传入对象的原型链上都会返回true
class Person{ name = "lnj"; } let p = new Person(); console.log(Person.prototype.isPrototypeOf(p)); // true class Cat{ name = "mm"; } console.log(Cat.prototype.isPrototypeOf(p)); // false function Person(myName) { this.name = myName; } function Student(myName, myScore) { Person.call(this, myName); this.score = myScore; } Student.prototype = new Person(); Student.prototype.constructor = Student; let stu = new Student(); console.log(Person.prototype.isPrototypeOf(stu)); // true
八 判断某一个对象是否拥有某一个属性
// 需求: 判断某一个对象是否拥有某一个属性 class Person{ name = null; age = 0; } Person.prototype.height = 0; let p = new Person(); // in的特点: 只要类中或者原型对象中有, 就会返回true console.log("name" in p); // true console.log("width" in p); // false console.log("height" in p); // true // 需求: 判断某一个对象自身是否拥有某一个属性 let p = new Person(); // 特点: 只会去类中查找有没有, 不会去原型对象中查找 console.log(p.hasOwnProperty("name")); // true console.log(p.hasOwnProperty("height")); // false
九 深拷贝和浅拷贝
1.什么是深拷贝什么是浅拷贝?
1.1深拷贝
修改新变量的值不会影响原有变量的值
默认情况下基本数据类型都是深拷贝
1.1浅拷贝
修改新变量的值会影响原有的变量的值
默认情况下引用类型都是浅拷贝
万能深拷贝方法
class Person{ name = "lnj"; cat = { age : 3 }; scores = [1, 3, 5]; } let p1 = new Person(); let p2 = new Object(); /* // p2.name = p1.name; // p2.name = "zs"; // console.log(p1.name); // console.log(p2.name); p2.cat = p1.cat; p2.cat.age = 666; console.log(p1.cat.age); console.log(p2.cat.age); */ depCopy(p2, p1); // console.log(p2); p2.cat.age = 666; console.log(p1.cat.age); console.log(p2.cat.age); function depCopy(target, source) { // 1.通过遍历拿到source中所有的属性 for(let key in source){ // console.log(key); // 2.取出当前遍历到的属性对应的取值 let sourceValue = source[key]; // console.log(sourceValue); // 3.判断当前的取值是否是引用数据类型 if(sourceValue instanceof Object){ // console.log(sourceValue.constructor); // console.log(new sourceValue.constructor); let subTarget = new sourceValue.constructor; target[key] = subTarget; depCopy(subTarget, sourceValue); }else{ target[key] = sourceValue; } } }