原型方式的继承
创建child object classes(constructors) , 子类如何从父类中继承特性。
原型链继承prototypal inheritance
(ruby中的继承也是这个模式)
使用prototype继承方法。
1. 属性写在函数体中, 非prototype属性中,因此是copy。
//
function Brick() {
this.width = 10;
this.height = 20;
}
Brick.prototype.circle = function() {
alert("this is circle!")
};
function BlueGlassBrick() {
Brick.call(this);
#this指向BlueGrassBrick()函数。
this.opacity = 0.5;
this.color = 'blue';
}
var p1 = new BlueGlassBrick()
=>
BlueGlassBrick { 10, height: 20, opacity: 0.5, color: "blue"}
解释:
p1中的属性都是从类BlueGlassBrick,拷贝下来的。
2. 使用原型prototype继承方法。
上面的BlueGlassBrick函数没有继承方法。
BlueGlassBrick.prototype = Object.create(Brick.prototype)
这样就继承了Brick的所有prototype中的方法/属性。
3. 改变构造器引用:
现在Teacher()
的prototype
的constructor
属性指向的是Person(),
改为指向自己:
BlueGlassBrick.prototype.constructor = BlueGlassBrick
4. 然后添加自己的方法: BlueGlassBrick.prototype.firstquality = function() { ... }
这样就OK了。
⚠️:
- 只有函数对象有prototype属性(因为Function对象定义了prototype属性)
- 当实例化对象时,JavaScript参考的是BlueGlassBrick.prototype指向的对象来生成实例的。
- BlueGlassBrick.prototype.constructor === BlueGlassBrick
- 由此可见:BlueGlassBrick()函数就是BlueGlassBrick.prototype的构造函数constructor
- 由此可见:BlueGlassBrick()函数就是BlueGlassBrick.prototype的构造函数constructor
- 任何想要被继承的方法都应该放置在构造函数的prototype对象里;同时永远使用父类的prototype来创建子类的prototype。这样结构才清晰。
总结:
对象,oop基础,原型和原型继承机制。 如何创建类constructors和对象实例,为类增加功能,通过从其他类继承而创建的子类。
注意: 在不同对象功能的共享通常被叫做--委托delegation。比称为继承更贴切。因为‘被继承’的功能并没有被copy到正在进行继承的对象中。
ECMAScript 2015
也叫ECMScritp6, 简写ES6 ,或者ecmascript2015, javascript6
- let, let声明允许你在一个scope内声明一个变量,自然也只在这个scope内有效。
- const 不可改变值。
- default parameter values:可以有默认参数值,function myFun(x, y = 10) { return x + y }
- Array.find(): 返回第一个找到的元素的值,必须通过测试函数。
- Array.findIndex() : 返回第一个找到的元素的index, 必须通过测试函数。
其他非重要:
增加2个Number 方法:
- Number.isInteger(10); // returns true
- Number.isSafeInteger() 有一个最大的范围,范围内是安全的
新的全局方法:
isFinite(10/0) //返回false ,是有限的。
isNaN(“hello”) //返回true ,数字返回false, 和Number.isNaN()不一样
Arrow Functions
无需function keyword, the return keyword和curly brackets
const x = (x, y) => x + y
⚠️,
- 箭头函数没有自己的this。
- 先定义再使用。
- 建议使用const
- const x = (x, y) => { return x * y }; 如果加上{} 就得加上return 。
let 详解 (点击)
新增block scope, 以前只有Global scope和 function scope。
变量声明为Globally 就有Global scope
变量声明为Locally(在一个函数内), 就有Function Scope
typeof "Jopn" //return "string"
typeof null //return "object"
用let 声明变量,可以包括在{ 。。。 }内,不能在外面使用。即只能在Block Scope中使用。
用var声明变量, 即使包括在{ 。。。}内, Block Scope不存在,没有任何效果。
Loop Scope 也算Block Scope的一种,对let, var声明的变量处理不一样。
Function Scope, 内部声明的 let, var变量都有函数作用域。
Global Scope , 在全局作用域下声明的let, var都有全局作用域
Global Variables in HTML
用JS, 全局作用域是JS环境。
在HTML, 全局作用域是window object。
var声明的变量属于window object: var carName = 'Vovo', 可以用window.carName得到值"Vovo"
let声明的变量和window object无关。
同一个作用域中,let, var不能先后声明一个相同的name。第二个声明会Not allowed
同一个作用域中, 相同的name, let只能声明一次。
let x = 2; // Allowed let x = 3; // Not allowed { let x = 4; // Allowed let x = 5; // Not allowed }
const
和let唯一的区别是不能改变value。
必须同时声明和赋值:
const PI = 3.14159265359;
用const声明的是变量,只不过值在声明后不能改变。primitive value不能改变。
但是:常量对象和常量array特殊
constant objects可以改变properties.
改变原来的值,或新增一个key/value对儿。
// You can create a const object: const car = {type:"Fiat", model:"500", color:"white"}; // You can change a property: car.color = "red"; // You can add a property: car.owner = "Johnson";
//但是,不能在分配一个常量对象
try {
var car = {type:"Fiat", model:"500", color:"white"};
car = {type:"Volvo", model:"EX60", color:"red"};
}
catch (err) {
document.getElementById("demo").innerHTML = err;
}
输出❌:TypeError: Assignment to constant variable.
同样Constant Arrays 也是可以改变其中的element,但不能再分配一个constant array。
const cars = ["Saab", "Volvo", "BMW"];
cars[0] = '123' ✅
cars.push("hha") ✅ cars = ["Toyota", "Volvo", "Audi"]; // ERROR
JS Errors (点击api)
- try{ ... } 让你测试一个块的代码,是否会出❌。
- The catch(err){ ... } 用于处理错误。
- The throw statement lets you create custom errors.
- The finally statement lets you execute code, after try and catch, regardless of the result.
Classes 新的syntax.
用传统类的方式:
class Person { constructor(first, last, age, gender, interests) { this.name = { first, last }; this.age = age; } greeting() { console.log(`Hi! I'm ${this.name.first}`); }; }
let han = new Person("Han", "Soo", 24)
han.greeting()
//Hi! I'm Han
⚠️,在hook下面,classes被转化为prototypal Inheritance models。类的写法只是语法糖。
类句法的继承写法:
使用extend关键字。
使用super()操作符在constructor()中。会调用父类的构造器并继承由super指定的参数。
class Teacher extends Person {
constructor(first, last, age, gender, interests, subject, grade) {
//都在constructor内部声明
super(first, last, age, gender, interests);
this.subject = subject;
this.grade = grade;
}
}
比传统写法有优势:
- 方法上,无需使用原型定义方法: Person.prototype.name = function() {}
- 继承上,也就无需Teacher.prototype = Object.create(Person.prototype), 然后再该指向:
- Teacher.prototype.constructor = Teacher
Getters and Setters
这两个是成对儿工作的。
a getter returns the current value of the variable
并且它响应setter changes the value of the variable to the one it defines.
class Teacher extends Person {
constructor(first, last, age, gender, interests, subject, grade) {
super(first, last, age, gender, interests);
this._subject = subject;
this.grade = grade;
}
get subject() {
return this._subject;
}
set subject(newSubject) {
this._subject = newSubject;
}
}
使用this._subject = subject
然后就可以修改subject储存的值了:
假设一个实例是snape, 熟悉的味道~:
snape.subject = "new value"