迎接关注前端小讴的github,浏览更多原创技术文章
用组织函数,天生对象实例:
- 运用组织函数,而且new 组织函数(), 背景会隐式实行new Object() 建立对象
- 将组织函数的作用域给新对象,(即new Object() 建立出的对象),函数体内的this代表new Object() 出来的对象
- 实行组织函数的代码
- 返回新对象( 背景直接返回)
function Person1(name, age) {
this.name = name
this.age = age
}
Person1.prototype.say = function () {
return "My name is " + this.name + ", I'm " + this.age + " years old."
}
var obj = new Person1("Simon", 28);
console.log(obj.say()); // My name is Simon, I'm 28 years old.
用class改写上述代码:
- 经由过程class关键字定义类,使得在对象写法上更清楚,让javascript更像一种面向对象的言语
- 在类中声明要领的时,不可给要领加function关键字
class Person2 {
// 用constructor组织要领吸收参数
constructor(name, age) {
this.name = name; // this代表的是实例对象
this.age = age;
}
// 类的要领,此处不能加function
say() {
return "My name is " + this.name + ", I'm " + this.age + " years old."
}
}
var obj = new Person2("Coco", 26);
console.log(obj.say()); // My name is Coco, I'm 26 years old.
- ES6中的类,实质上就是一个函数
- 类本身指向的就是组织函数
- 类实在就是组织函数的别的一种写法
console.log(typeof Person2); // function
console.log(Person1 === Person1.prototype.constructor); // true
console.log(Person2 === Person2.prototype.constructor); // true
组织函数的prototype属性,在ES6的class中依旧存在:
// 组织1个与类同名的要领 -> 胜利完成掩盖
Person2.prototype.say = function () {
return "证实一下:My name is " + this.name + ", I'm " + this.age + " years old."
}
var obj = new Person2("Coco", 26);
console.log(obj.say()); // 证实一下:My name is Coco, I'm 26 years old.
// 经由过程prototype属性对类增添要领
Person2.prototype.addFn = function () {
return "经由过程prototype新增添的要领addFn"
}
var obj = new Person2("Coco", 26);
console.log(obj.addFn()); // 经由过程prototype新增添的要领addFn
经由过程Object.assign要领来为对象动态增添要领:
Object.assign(Person2.prototype, {
getName: function () {
return this.name;
},
getAge: function () {
return this.age;
}
})
var obj = new Person2("Coco", 26);
console.log(obj.getName()); // Coco
console.log(obj.getAge()); // 26
constructor要领是类的组织函数的默许要领
new天生对象实例时,自动挪用该要领
class Box {
constructor() {
console.log("自动挪用constructor要领"); // 实例化对象时,该行代码自动实行
}
}
var obj = new Box();
若没有定义constructor要领,将隐式天生一个constructor要领:
- 纵然没有增添组织函数,组织函数也是存在的
- constructor要领默许返回实例对象this
- 能够指定constructor要领返回一个全新的对象,让返回的实例对象不是该类的实例对象
class Text1 {
constructor() {
this.text = "这是一段Text";
}
}
class Text2 {
constructor() {
return new Text1(); // 返回一个全新的对象
}
}
var obj = new Text2()
console.log(obj.text); // 这是一段Text
实例属性:constructor中定义的属性,即定义在this对象上
原型属性:constructor外声明的属性,即定义在class上
- hasOwnProperty() 函数,推断属性是不是为实例属性 -> true or false
- in操作符, 推断对象可否接见给定属性 -> true or false(与该属性存在于实例/原型中无关)
class Text3 {
// 实例属性,定义在this对象上
constructor(text1, text2) {
this.text1 = text1
this.text2 = text2
}
// 原型属性,定义在class上
text3() {
return text1 + text2
}
}
var obj = new Text3('123', '234')
console.log(obj.hasOwnProperty("text1")); // true
console.log(obj.hasOwnProperty("text2")); // true
console.log(obj.hasOwnProperty("text3")); // false
console.log("text1" in obj); // true
console.log("text2" in obj); // true
console.log("text3" in obj); // true
console.log("text4" in obj); // false
类的一切实例同享一个原型对象, 它们的原型都是Person.prototype, 所以proto属性是相称的
class Text4 {
constructor(text1, text2) {
this.text1 = text1;
this.text2 = text2;
}
text3() {
return text1 + text1;
}
}
// text1与text2都是Text4的实例 -> 它们的__proto__都指向Text4的prototype
var text1 = new Text4('1234', '5678');
var text2 = new Text4('4321', '8765');
console.log(text1.__proto__ === text2.__proto__); // true
经由过程proto来为类增添要领:
- 运用实例的proto属性改写原型
- 会转变Class的原始定义,影响到一切实例,不引荐运用
class Num {
constructor(num1, num2) {
this.num1 = num1;
this.num2 = num2;
}
sum() {
return num1 + num2;
}
}
var num1 = new Num(20, 78);
var num2 = new Num(40, 96);
num1.__proto__.minus = function () {
return this.num2 - this.num1;
}
console.log(num1.minus()); // 76 -> 转变了class的原始定义,为class新增原型属性minus
console.log(num2.minus()); // 20 -> num2和num1同享原型对象Num,能够挪用原型对象的minus要领
class不存在变量提拔,必须先定义再运用:
- ES6不会把class的声明提拔到代码头部2
- ES5存在变量提拔, 能够先运用再定义
//ES5能够先运用再定义,存在变量提拔
new A()
function A() {}
//ES6不能先运用再定义,不存在变量提拔(报错)
new B() // B is not defined
class B {}