//ES5构造函数
function Person(){
this.name='建林';
this.age=18;
this.say=function(){
console.log('person的say')
}
}
let p1=new Person();
console.log(p1.name);
console.log(p1.__proto__); //{constructor: ƒ}
p1.say();
//ES6 构造函数与继承
//ES6语法 class
class Person {
constructor() {
this.name = "建林";
this.age = 18;
}
say() {
console.log('person的say')
}
}
let p2 = new Person();
console.log(p2.name);
p2.say();
//ES6构造函数继承
class Child extends Person{
constructor(){
//继承必须加super()
super();
this.sex="男";
this.name="思聪";//覆盖父亲的name属性
this.score=1000;
}
hello(){
console.log('hello');
}
abc(){
console.log(abc);
}
}
let p3=new Child();
console.log(p3); // Child {name: '思聪', age: 18, sex: '男', score: 1000}
console.log(p3.__proto__); //Person {constructor: ƒ, hello: ƒ, abc: ƒ} p3通过原型链指向Child构造函数,但继承Person,constructor里是class Child
console.log(p3.__proto__.__proto__); // {constructor: ƒ, say: ƒ} constructor里是 class Person
console.log(Person.prototype===p3.__proto__.__proto__); //true
console.log(p3.name);//思聪
p3.say() //person的say
p3.hello()//hello
const b=new A(); b.fn() 和 const b=new A().fn; b() 中的this指向区别
//b.fn()中b直接调用了则指向构造函数,而后面一种写法没调用者,默认指向全局window
class类和new构造函数的区别:
总结区别:
1.es6引进了class,class定义的类中的方法要是没对象调用,则this直接指向undefined(可能class做了处理,会把在非严格模式下的this指向转为严格模式下的this指向,class相对严格),new构造函数中的方法没对象调用时,遵循默认绑定规则(默认绑定:默认情况下,没有直接调用者,在非严格模式下,this指向window ,严格模式下(设置了’use strict’),this为undefined )。
2. c=7这种写法在class类和new构造函数中写了都不会报错,但不够严谨,错误写法。这样定义的变量在new构造函数中是会被包含在全局中,但不在构造函数中,比较严格;而class中这样定义的变量还会包含在class中,不会出现在全局中,相对不是很严格 (正好相反)
3. 控制台打印显示的区别(可忽略,很少考查)
例子:
class类:
var a=5;
class A{
c=7 // 这种写法也可以 简单写法
constructor(){ //复杂写法
this.a=10
d=7 //控制台直接报错,d is not defined
}
fn()
{
console.log(this); //A {c: 7, a: 10},fn在下一级,没展开
console.log(this.a); //10
console.log(this.c); //7
}
}
const b=new A()
b.fn()
console.log(this.a); //5
//c=7这样定义的变量在new构造函数中是会被包含在全局中,但不在构造函数中,
//而class中这样定义的变量只会包含在class中,不会出现在全局中,比较严格
console.log(this.c); //undefined
var a=5;
class A{
c=7
constructor(){
this.a=10
d=7 //控制台直接报错,d is not defined
}
fn()
{
console.log(this); //undefined class中不像构造函数没人调用会默认指向全局
console.log(this.a); //报错 Cannot read properties of undefined (reading 'a')
console.log(this.c); //报错 Cannot read properties of undefined (reading 'c')
}
}
const b=new A().fn
b() //没人直接调用b方法 默认指向全局,严格模式,undefined
console.log(this.a); //5
//c=7这样定义的变量在new构造函数中是会被包含在全局中,但不在构造函数中,
//而class中这样定义的变量只会包含在class中,不会出现在全局中,比较严格
console.log(this.c); //undefined
new构造函数:
let d=10
var e=8
function Person(nam){
age=10,//不可以这样写,不会被包含在Person对象中,会被提升到全局,不够严谨
this.nam=nam;
this.fn=function(){
console.log(this); //指向全局
console.log(this.nam); //undefined name只在Person中
}
}
var p = new Person("abc").fn;
p() //没人直接调用p方法,this默认指向全局
console.log(this.d); // undefined let块级作用域不会出现在全局中
console.log(d); //10 当前块级中有
console.log(this.e); //8
console.log(this.age);//10 age会被提升到全局作用域中
console.log(this.nam); //undefined name只在Person中
let score=50
var age2=30
let d=10
var e=8
function Person(nam){
age2=40
score=60
age=10,//不可以这样写,不会被包含在Person对象中
this.nam=nam;
this.fn=function(){
console.log(this); //Person {nam: 'abc', fn: ƒ}
console.log(this.nam); //abc
}
}
var p = new Person("abc");
p.fn()
console.log(this) //全局
console.log(this.d); // undefined let块级作用域不会出现在全局中
console.log(d); //10 当前块级中有
console.log(this.e); //8
console.log(age); //10
console.log(this.age);//10 age会被提升到全局作用域中
console.log(this.nam); //undefined name只在Person中
console.log(score); //60 构造函数中重新赋值一遍
console.log(this.score); //undefined let块级作用域不会出现在全局中
console.log(age2); //40 构造函数中重新赋值一遍
console.log(this.age2); //40 //全局中
3.控制台打印的区别:
//ES5构造函数
function Person(name) {
this.name = name;
this.says=function () {
console.log("哈哈");
};
}
Person.prototype.say = function () {
console.log("哈哈哈");
};
const p1 = new Person("张三");
console.log(p1); //Person {name: '张三', says: ƒ} 内部属性和方法都会显示,原型上的不会显示
console.log(p1.__proto__); //{say: ƒ, constructor: ƒ} es5中定义在内部的方法不会显示,原型上的才会显示
console.log(p1.__proto__.__proto__); //对象原型
console.log(p1.__proto__.__proto__.__proto__); //空
//ES6 class 构造函数
class Person {
constructor() {
this.name = "建林";
this.age = 18;
}
say() {
console.log('person的say')
}
}
Person.prototype.say2 = function () {
console.log("哈");
};
let p2 = new Person();
console.log(p2); //Person {name: '建林', age: 18} //只打印内部的的属性,内部的方法和原型上的方法和属性都不会打印
console.log(p2.__proto__); //{say2: ƒ, constructor: ƒ, say: ƒ} //ES6 class中直接定义在class和prototype中的方法都会在控制台打印出来,constructor的f就是class Person
console.log(p2.__proto__.__proto__); //对象原型
console.log(p2.__proto__.__proto__.__proto__); //null