## class expression: const Person = class { } ## class declaration: class Person { constructor(fName, bYear){ this.fName = fName; this.bYear = bYear; } calcAge(){ console.log(2024 - this.bYear); } } - constructor is a method of this class. Pass values for properties to have in objects created using this fn. - then set the properties of the object using this.xxx = xxx; - On using 'new' operator, this constructor will be called automatically and return a new object which will be stored in LHS variable as shown below. Ex. const ronald = new Person('ronald',1975); // Person { fName: 'ronald', bYear: 1975 } - Methods are written outside the constructor fn and will be added to the prototype property of the object which can be verified using devConsole. Ex. ronald.calcAge(); // 49 ronald.__proto__ === Person.prototype; // true - No commas need to be added while adding multiple methods below the constructor fn inside the class. ## Hence, the above syntax works same as constructor fn syntax but with a familiar syntax of strongly typed class based languages. ## Adding a fn explicitly to the prototype: Person.prototype.greet = function(){ console.log(`Hey ${this.fName}`); } ronald.greet(); // 'Hey ronald'
导入点:
访问器属性:获取器和设置器,即获取和设置值的 fns。但从外观上看,它们仍然像普通房产一样。
普通属性称为数据属性。
const account = { owner: 'jonas', movements: [200,300,100,500], get latest(){ // will return an array with last value. Hence, use pop to get the value. return this.movements.slice(-1).pop(); }, set latest(mov){ this.movements.push(mov); } } account.latest; // 500 account.latest = 50; account.latest; // 50 Just like above, classes also support the getter-setter methods but acccessed like using a property syntax. These are very useful for data validation.
例如。 Array.from() = 将类似数组的结构转换为数组。
Array.from(document.querySelector('h1'));
Array.from(document.querySelectorAll('h1'));
例如。 .from 附加到数组构造函数,而不是构造函数的原型属性。因此,并非所有数组都继承此 fn。
[1,2,3].from(); // .from 不是函数
例如。 Number.parseFloat(12) 是 Number 构造函数上的静态方法,不适用于数字变量。
// Static methods are not inherited. They are not added to prototype. className.fnName = function(){ console.log(this); // Entire constructor() which is calling the method console.log("JS is awesome") }; className.fnName(); // Rule = whatever object is calling the method, 'this' points to that object inside the fn. Hence its simply the entire constructor() above. //Inside class, we need to use static keyword for adding a static method. static fnName = function(){ console.log(this); // can point to the entire class defn console.log("JS is awesome") }; // Static methods and instance methods will be different from each other. // instance methods will be prototype, hence all instances can have access to them
手动用于将对象的原型设置为我们想要的任何对象。
将用于实现继承黑白类。
使用此 fn 实现原型继承。
Object.create 返回一个空对象。
与构造函数 fns 和类的工作方式不同。
即使不涉及“prototype”、“constructor()”、“new”运算符,仍然存在原型继承的想法。
const PersonProto = { // This method will be looked up using __proto__ link calcAge(){ console.log(2024 - this.bYear); } }; // baba will be created, with its prototype set to PersonProto object. const baba = Object.create(PersonProto); baba; baba.name = 'Roger'; baba.bYear = '2000'; baba.calcAge();
构造函数 Fn --(.prototype)--> Person.prototype
对象实例 --(proto)--> Person.prototype
工作方式就像在 fn 构造函数或类中一样
不需要 constructor() 或 .prototype 属性来实现此目标。
const PersonProto = { // This method will be looked up using __proto__ link calcAge(){ console.log(2024 - this.bYear); }, // Noting special with init name, its a normal fn here. // This has nothing to with ES6 constructor() // Manual way of initialzing an object. init(fName, bYear){ this.fName = fName; this.bYear = bYear; } }; // baba will be created, with its prototype set to PersonProto object. const baba = Object.create(PersonProto); baba; baba.name = 'Roger'; baba.bYear = '2000'; baba.calcAge(); baba.__proto__; // { calcAge: [Function: calcAge] } baba.__proto__ === PersonProto; //true const alice = Object.create(PersonProto); alice.init("alice", 2000); alice; // { fName: 'alice', bYear: 2000 }
创建原型继承的方法:
构造函数 Fn
ES6 类
对象.create
所有这些技术都允许对象在其原型上查找方法。
JS 中不存在真正的类。
const Person = function(firstName, bYear){ this.firstName = firstName; this.bYear = bYear; }; Person.prototype.calcAge = function(){ console.log(2024 - this.bYear); }; const Student = function(firstName, bYear, course){ // This is the duplicate code, any change in Person won't be reflected here. this.firstName = firstName; this.bYear = bYear; this.course = course; }; Student.prototype.introduce = function(){ console.log(`My name is ${this.firstName} and I study ${this.course}`); } const matt = new Student("Matt", 2000, "CSE"); matt.introduce(); // 'My name is Matt and I study CSE'
const Person = function(firstName, bYear){ this.firstName = firstName; this.bYear = bYear; }; Person.prototype.calcAge = function(){ console.log(2024 - this.bYear); }; const Student = function(firstName, bYear, course){ // Person(firstName, bYear); -> This doesn't work because we are calling it as a regular fn call. 'new' has to be used to call this fn constructor. This fn call is simply a regular fn call, in which 'this' is set 'undefined'. Hence, an error as it cannot set firstName on undefined. // We want to set the 'this' inside this fn to be same as inside Person above. Person.call(this, firstName, bYear); this.course = course; }; Student.prototype.introduce = function(){ console.log(`My name is ${this.firstName} and I study ${this.course}`); } const matt = new Student("Matt", 2000, "CSE"); matt.introduce(); // 'My name is Matt and I study CSE'
'new' 通过 proto
在对象实例与其原型之间自动建立链接
继承的整体思想是子类可以共享原型链上父类的行为。
原型[Object.prototype] = null; // 位于原型链的顶部。
const Person = function(firstName, bYear){ this.firstName = firstName; this.bYear = bYear; }; Person.prototype.calcAge = function(){ console.log(2024 - this.bYear); }; const Student = function(firstName, bYear, course){ Person.call(this, firstName, bYear); this.course = course; }; // Student.prototype = Person.prototype; => This doesn't work because we won't get the prototype chain, rather we will get // Constructor fn[i.e Person()] --------------> Person.prototype // Constructor fn[i.e Student()] --------------> Person.prototype // Object [Matt] __proto__: Student.prototype ---> Person.prototype // Student.prototype manually linked for lookup to Person.prototype. // This has to be done here and not after else Object.create will overwrite any of the existing methods like introduce() on it. Student.prototype = Object.create(Person.prototype); Student.prototype.introduce = function(){ console.log(`My name is ${this.firstName} and I study ${this.course}`); } const matt = new Student("Matt", 2000, "CSE"); matt.introduce(); // 'My name is Matt and I study CSE' matt.calcAge(); // 24 matt.__proto__; // Person { introduce: [Function (anonymous)] } matt.__proto__.__proto__; // { calcAge: [Function (anonymous)] } matt.__proto__.__proto__.__proto__; // [Object: null prototype] {} Student.prototype.constructor = Student; // [Function: Student] matt instanceof Student; // true matt instanceof Person; // true matt instanceof Object; // true
以上是JS 中的 OOP -的详细内容。更多信息请关注PHP中文网其他相关文章!