ES6-学习笔记-(二)

本文详细解析了Proxy和Promise在JavaScript中的应用与原理,包括Proxy的构造、实例方法及Promise的解决异步编程问题的方式。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Proxy

Proxy 用于修改某些操作操作的默认行为,可以理解为在目标对象前架设了一个 “拦截层” ,外界对该对象的访问需要先通过这层拦截,提供了一种机制可以对外界的访问进行过滤和改写。

var obj = new Proxy({},{
    get: function(target,key,receiver){
        console.log(`getting ${key}`);
        return Reflect.get(target,key,receiver)
    },
    set:function(target,key,value,receiver){
        console.log(`setting ${key} setting ${value}`);
        return Reflect.set(target,key,value,receiver)
    }
})
obj.a = 1; //setting a setting 1
console.log(obj.a) //getting a 1
复制代码

构造函数 Proxy 接受两个参数,第一个参数接受需要代理的对象,第二个参数是一个配置对象,对于每一个代理操作,需要提供一个对应的处理函数,该函数将拦截对应的操作

Proxy 实例方法
get(target, propKey, receiver)

拦截对象属性的读取,最后一个参数是一个可选对象

var person = {
    name:'xy'
}
var proxy = new Proxy(person, {
    get(target, key, receiver){
        if(key in target){
            return target[key]
        }else{
            return `${key} does not exist`
        }
    }
})
console.log(proxy.name);
console.log(proxy.age);
// get方法 可以继承
var extendObj = Object.create(proxy)
console.log(extendObj.name); //xy
console.log(proxy.age); //age does not exist

function createArray(...element){
    let handler = {
        get(target, key, receiver){
            let index = Number(key);
            if(index < 0){
                key = String(target.length + index);
            }
            return Reflect.get(target,key,receiver);
        }
    }
    let target  = [];
    target.push(...element);
    return new Proxy(target, handler);
}

var arr = createArray(1,2,3,4,5);
console.log(arr[1]) //2
console.log(arr[-1]) //5

//链式使用函数的实例
var pipe = (function(){
    return function(value){
        var funcStack = [];
        var oProxy = new Proxy({},{
            get(pipeObject, fnName){
                if(fnName === 'get'){
                    return funcStack.reduce(function (val, fn){
                        return fn(val);
                    }, value)
                }
                funcStack.push(window[fnName]);
                return oProxy
            }
        })
        return oProxy;
    }
}())

var double = n => n*2;
var pow = n => n*n;
var reverseInt = n => n.toString().split('').reverse().join('') || 0;
console.log(pipe(3).double.pow.reverseInt.get); //63
复制代码
set(target, propKey, value, receiver)

拦截某个属性的赋值操作,返回一个布尔值

var person = {
    name:'xy'
}
var proxy = new Proxy(person, {
    get(target, key, receiver){
        if(key in target){
            return target[key]
        }else{
            return `${key} does not exist`
        }
    },
    set(target, key, value){
        if(key[0] === '_'){
            console.log(`${key} is private property`)
        }else{
            target[key] = value
        }
    }
})

console.log(proxy.name); //xy
proxy.age = '';
proxy.age = 15; 
proxy._age = 15; //_age is private property
console.log(proxy.age); // 15
复制代码
apply(target, object, args)

拦截函数调用、call和apply操作

var targetF = function(){}
var proxyF = new Proxy(targetF, {
    apply(target, ctx, args){
        return 'I am the proxy'
    }
})
console.log(proxyF())//I am the proxy
console.log(proxyF.call(person)); //I am the proxy
console.log(proxyF.apply(person)); //I am the proxy
复制代码
has(target, propKey)

拦截 hasProperty 操作,判断某个对象是否有某个属性时,调用这个方法

var person = {
    name:'xy',
    _age:10
}
var proxy = new Proxy(person, {
    has(target, key){
        if(key[0] === '_'){
            return false
        }
        return key in target
    }
})

console.log('_age' in proxy); //false
console.log('age' in proxy); //true
复制代码
construct(target, args)

用于拦截 new 命令

var handler = {
    construct(target, args, newTarget){
        // target 目标对象  args 构造函数的参数对象
        return new target(...args);
    }
}
var p = new Proxy(function(){}, {
    construct(target, args, newTarget){
        console.log(`caller ${args.join(',')}`)
        //必须返回一个对象 否则报错
        return { value: args[0] * 10 }
    }
})
console.log((new p(1)).value)
复制代码
deleteProperty(target, propKey)

拦截 delete 操作,如果这个方法抛出错误或者返回 false ,当前属性就无法被 delete 删除。

var handler = {
    deleteProperty(target, key){
        this.invariant(key)
        return true;
    },
    invariant(key, action){
        if(key[0] === '_'){
            throw new Error(`${key} is private property`)
        }
    }
}
var target = {age: 10, _age:10};
var dProxy = new Proxy(target, handler)
delete dProxy.age
delete dProxy._age //报错 _age is private property
复制代码
setPrototypeOf(target)

拦截 Object.defineProperty 操作

var handler = {
    defineProperty(target, key, descriptor){
        // 返回 false 无法添加新属性
        return false
    }
}
var target = {};
var dProxy = new Proxy(target, handler);
dProxy.a = 1; 
console.log(dProxy.a) //undefined
复制代码
getOwnPropertyDescriptor(target, propKey)

拦截 Object.getOwnPropertyDescriptor() 返回一个属性描述对象或者 undefined

var handler = {
    getOwnPropertyDescriptor(target, key){
        if(key[0] === '_')return 
        return Object.getOwnPropertyDescriptor(target, key);
    }
}
var target = {a: 1, _a: 1};
var dProxy = new Proxy(target, handler);
console.log(Object.getOwnPropertyDescriptor(dProxy, 'a')) //{ value: 1, writable: true, enumerable: true, configurable: true }
console.log(Object.getOwnPropertyDescriptor(dProxy, '_a')) //undefined
复制代码
getPrototypeOf(target)

拦截获取对象原型,一般用于拦截以下操作

  • Object.prototype.proto
  • Object.prototype.isPrototypeOf()
  • Object.getPrototypeOf()
  • Reflect.getPrototypeOf()
  • instanceof
var proto = {};
var p = new Proxy({}, {
    getPrototypeOf(target){
        return proto;
    }
})
console.log(p.__proto__ === proto); //true
console.log(Object.prototype.isPrototypeOf(p)); //true
console.log(Object.getPrototypeOf(p) === proto); //true
console.log(Reflect.getPrototypeOf(p) === proto); //true
复制代码
isExtensible(target)

拦截 Object.isExtensible 操作

var eProxy = new Proxy({},{
    isExtensible(target){
        console.log('proxy caller')
        return true
    }
})
console.log(Object.isExtensible(eProxy)) //proxy caller true
复制代码
ownKeys(target)

拦截对象自身属性的读取操作。

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
var target = {
    a: 1,
    b: 2,
    _c:1,
    [Symbol.for('a')]:1
}
Object.defineProperty(target, 'key', {
    enumerable:false,
    value:'value'
})
var proxy = new Proxy(target,{
    ownKeys(target){
        return Reflect.ownKeys(target).filter(key =>  key[0] !== '_')
    }
})
console.log(Object.keys(proxy)) // [ 'a', 'b' ]
console.log(Object.getOwnPropertySymbols(proxy)) // [Symbol(a)]
console.log(Object.getOwnPropertyNames(proxy)) // ['a','b', 'key']
复制代码
preventExtensions(target)

拦截 Object.preventExtensions(),这个方法必须返回一个布尔值,否则自动转为布尔值,只有在目标不可扩展的时候,才能返回true

setPrototypeOf(target, proto)

拦截 Object.setPrototypeOf 方法

revocable()

返回一个可取消的 Proxy 实例

var target = {}
var {proxy, revoke} = Proxy.revocable(target, {});
proxy.a = 1
console.log(proxy.a); //1
revoke(); //取消代理
console.log(proxy.a); //报错
复制代码

Reflect

Reflect 对象是 ES6 为了操作对象提供的新的API

  • 将 Object 一些明显的属于语言内部的方法放在 Reflect 对象上,未来新的方法只在 Reflect 部署
  • 修改某些 Object 对象方法的返回结果,让其变得更合理
静态方法
Reflect.apply(target,thisArg,args)

等同于 Function.prototype.apply,用于绑定 this 对象后执行指定函数

var obj = {
    value : 2
}
var value = 1;

function print(value) {
    console.log(value,this.value)
}

print.call(obj,'value') // value 2
print.apply(obj,['value'])// value 2

Reflect.apply(print,obj,['r-value']);// r-value 2
print('g-value');// g-value 1
复制代码
Reflect.construct(target,args)

等同于 new target(...args),提供了一种不使用 new 来调用构造函数的方法

function target(value){
    this.value = value
}
var o = Reflect.construct(target,['r-value'])
console.log(o); //target { value: 'r-value' }
复制代码
Reflect.get(target,name,receiver)

查找并返回 target 对象的 name 属性,如果没有该属性,返回 undefined

var o = {
    a:1,
    b:2,
    get c(){
        return 'get' + this.b + this.a
    }
}
var nO = {
    a:2,
    b:1
}
console.log(Reflect.get(o,'c')) // get21
console.log(Reflect.get(o,'c',nO)) //get12
复制代码
Reflect.set(target,name,receiver)

设置 target 对象的 name 属性的 value 值。

var o = {
    a:1,
    b:2,
}
Reflect.set(o,'d',3);
console.log(o); //{ a: 1, b: 2, d: 3 }
复制代码
Reflect.defineProperty(target,name,desc)

等同于 Object.defineProperty ,用来为对象定义属性

var o = {};
Object.defineProperty(o,'value',{
    enumerable:true,
    value:'123'
})
Reflect.defineProperty(o,'rValue',{
    enumerable:true,
    value:'rValue'
})
console.log(o) //{ value: '123', rValue: 'rValue' }
复制代码
Reflect.deleteProperty(target,name)

等同于 delete target[name] 用于删除对象属性

var o = {
    value:1
};
Reflect.deleteProperty(o,'value')
console.log(o) //{}
复制代码
Reflect.has(target,name)

对应 in 运算符

var o = {
    value:1
};
console.log(Reflect.has(o,'value')) // true
复制代码
Reflect.ownKeys(target)

返回对象所有的属性

var o = {
    value:1,
    [Symbol('a')]:1
};
Reflect.defineProperty(o,'em',{
    enumerable:false,
    value:1
})
console.log(Reflect.ownKeys(o)) //[ 'value', 'em', Symbol(a) ]
复制代码
Reflect.isExtensible(target)

返回一个布尔值,表示当前对象是否支持可以扩展

console.log(Reflect.isExtensible(o)) // true
复制代码
Reflect.preventExtensions(target)

返回一个布尔值,表示是否操作成功,使一个对象变不可扩展

var o = {
    value:1,
    [Symbol('a')]:1
};
Reflect.defineProperty(o,'em',{
    enumerable:false,
    value:1
})
console.log(Reflect.preventExtensions(o)); //true
console.log(Reflect.isExtensible(o)) // false
o.b = '1'
console.log(Reflect.ownKeys(o)) //[ 'value', 'em', Symbol(a) ]
复制代码
Reflect.getOwnPropertyDescriptor(target,name)

代替 Object.getOwnPropertyDescriptor 用于获取对象指定属性的描述对象

var o = {
};
Reflect.defineProperty(o,'em',{
    enumerable:false,
    value:1
})
console.log(Reflect.getOwnPropertyDescriptor(o,'em'))//{ value: 1, writable: false, enumerable: false,configurable: false }
复制代码
Reflect.getPrototypeOf(target)

读取对象的 __proto__ 属性

var o = {}
console.log(Reflect.getPrototypeOf(o) === Object.prototype) // true
复制代码
Reflect.setPrototypeOf(target,prototype)

设置对象的 __proto__ 属性

var o = {}
var p = {}
Reflect.setPrototypeOf(o,p)
console.log(Reflect.getPrototypeOf(o) === Object.prototype) // false
console.log(Reflect.getPrototypeOf(o) === p) // true
复制代码

Promise

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

Promise 有两个特点
  1. 对象的状态不受外界影响,Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(完成)和rejected(失败)。
  2. 异步操作的结果来决定是哪种状态,一旦决定变不会改变 pending => fulfilled | pending => rejected
缺点
  1. 无法取消 Promise
  2. 一旦新建则立即执行,中途无法取消
  3. 如果不设置回调函数,抛出错误无不会反应到外部
  4. 你无法知道进展到哪一阶段
用法

Promise对象是一个构造函数,用来生成Promise实例

接受一个函数作为参数,该函数两个参数分别为 resolve 和 reject 两个函数,由JavaScript引擎提供。

Promise.prototype.then()

Promise 实例具有 then 方法,他的作用是为 Promise 实例添加状态改变时的回调函数。第一个参数是 Resolved 状态的回调函数,第二个参数是 Rejected 状态的回调函数。返回一个新的 Promise 实例。进而实现链式操作

// Promise对象是一个构造函数,用来生成Promise实例
// 接受一个函数作为参数,该函数两个参数分别为 resolve 和 reject 两个函数,由JavaScript引擎提供。
var promise = new Promise(function(resolve,reject){
    var value = 'promise';
    console.log(value);
    if(Math.random() > 0.3){
        resolve(value)
    }else{
        reject(value)
    }
})

var then = promise.then(function(value){
    value = value + ' - resolve'
    console.log(value);
    return new Promise(function(resolve,reject) {
        reject(value)
    });
},function(value){
    value = value + ' - reject'
    console.log(value);
    return new Promise(function(resolve,reject) {
        resolve(value)
    });
})
console.log(then);
then.then(function(value){
    value = value + ' - resolve'
    console.log(value);
    return value;
},function(value){
    value = value + ' - reject'
    console.log(value);
    return value;
})
// promise
// promise - resolve
// promise - resolve - reject
// promise - reject - resolve
复制代码

Promise.prototype.catch()

用于指定发生错误的时候的回调函数

var promise = new Promise((resolve,reject)=>{
    var value = 'promise';
    console.log(value);
    if(Math.random() > 0.3){
        resolve(value)
    }else{
        reject(value)
    }
})
// bad
var then = promise.then( value => {
    value = value + ' - resolve'
    console.log(value);
    throw new Error('test');
    return new Promise((resolve,reject) => reject(value));
}, value => {
    value = value + ' - reject'
    console.log(value);
    return new Promise((resolve,reject) => resolve(value));
}).catch(error=>{
    console.log(error)
})
//good
var promise = new Promise((resolve,reject)=>{
    if(Math.random() > 0.3){
        resolve('data')
    }else{
        throw new Error('报错了')
    }
})
promise.then(data => {
    console.log(data)
}).catch(err => {
    console.log(err)
})
复制代码
Promise.all([])

用于将多个 Promise 实例包装成一个新的 Promise 实例,当数组中的 Promise 对象的状态都变成 Fulfilled 新的实例对象才会变成 Fulfilled ,其中只要有一个失败,就会变成 rejected

var p1 = new Promise((resolve,reject) => {
    var time = setTimeout(() => {
        clearTimeout(time);
        console.log('p1');
        resolve('p1');
    }, 3000);  
})
var p2 = new Promise((resolve,reject) => {
    var time = setTimeout(() => {
        clearTimeout(time);
        console.log('p2');
        resolve('p2');
    }, 4000);  
})
var p3 = new Promise((resolve,reject) => {
    var time = setTimeout(() => {
        clearTimeout(time);
        console.log('p3');
        // throw new Error('p3');
        resolve('p3');
    }, 5000);  
}).catch(err =>{
    console.log(err)
})
var promise = Promise.all([p1, p2, p3]) 
// 这个实例的 catch 无法捕获到数组实例的报错,只能再数组实例中捕获
promise.then(posts => {
    console.log(posts)  // ['p1','p2','p3']
})
复制代码
Promise.race()

用于将多个 Promise 实例包装成一个新的 Promise 实例,当数组中的 Promise 对象的状态第一个变成 Fulfilled 新的实例对象才会变成 Fulfilled ,全部失败或者没有得到结果,就会变成 rejected

var p1 = new Promise((resolve,reject) => {
    var time = setTimeout(() => {
        clearTimeout(time);
        console.log('p1');
        resolve('p1');
    }, 3000);  
})
var p2 = new Promise((resolve,reject) => {
    var time = setTimeout(() => {
        clearTimeout(time);
        console.log('p2');
        resolve('p2');
    }, 4000);  
})
var p3 = new Promise((resolve,reject) => {
    var time = setTimeout(() => {
        clearTimeout(time);
        console.log('p3');
        // throw new Error('p3');
        resolve('p3');
    }, 5000);  
}).catch(err =>{
    console.log(err)
})
var promise = Promise.race([p1, p2, p3]) 
// 这个实例的 catch 无法捕获到数组实例的报错,只能再数组实例中捕获
promise.then(response => {
    console.log(response) // p1
})
复制代码
Promise.resolve()

将现有对象转为 Promise 对象。状态为 resolve


// 如果参数为 Promise 实例,将不做修改,直接返回该对象
Promise.resolve(new Promise())
//参数是一个具有 then 方法的对象
// 直接执行 then 方法
var p1 = Promise.resolve({
    then(resolve,reject){
        console.log('then');
        resolve(42)
    }
})
p1.then(value => {
    console.log(value) // 42
})
//参数是不具有then方法的对象,或者不是对象
var p2 = Promise.resolve('hello');
p2.then(s=>console.log(s));
//不传参数
// 直接返回一个 Resolved 状态的 Promise
var p3 = Promise.resolve();
p3.then(()=>{
    console.log('p3')
})
复制代码
Promise.reject()

将现有对象转为 Promise 对象。状态为 rejected

Iterator 和 for..of 循环

Iterator (遍历器) 是一种通过统一接口机制来处理不一样的数据结构。他是一个接口,只要任何数据结构部署了 Iterator 接口 就可以完成遍历操作。

Iterator 接口主要供 for...of 使用

Iterator 的遍历过程

  • 创建一个指针对象,指向当前数据结构的起始位置。
  • 第一次调用指针对象的 next 方法,指针指向第一个成员,以此类推,直到最后结束位置

默认的 Iterator 接口部署在数据结构的 Symbol.iterator 属性,只有部署过的既可以认为是一个可便利的数据结构。可以使用 for..of 循环

原生具备 Iterator 接口的数据结构有

  • Array
  • Map
  • Set
  • String
  • TypedArray
  • arguments对象
  • NodeList对象
手动部署一个对象可以被 for...of 循环
let obj = {
    data:[1,2,3,4,5],
    [Symbol.iterator](){
        const self = this;
        let index = 0;
        return {
            next(){
                if(index < self.data.length){
                    return {
                        value:self.data[index++],
                        key:index,
                        done:false
                    }
                }else{
                    return{
                        value:undefined,
                        done:true
                    }
                }
            }
        }
    }
}
for (let item of obj) {
    console.log(item) //1 2 3 4 5
}


var str =  new String('str');

str[Symbol.iterator] = function(){
    return {
        next(){
            if(this.index<3){
                this.index++
                return {value:'+1',done:false}
            }else{
                return {value:undefined,done:true}
            }
        },
        index:0
    }
}

console.log([...str]) // ['+1','+1','+1']

复制代码

Generator

Generator 函数是 ES6 提供的一种异步编程方案,可以将其理解为一个状态机,封装了多个内部状态。

function* helloGenerator(){
    yield 'hello';//相当于暂停标志
    yield {a:'Generator'}
}
var hg = helloGenerator();//helloGenerator {<suspended>} 遍历器对象,调用next()进行下一步
console.log(hg);//{ value: 'hello', done: false }
console.log(hg.next());//{ value: 'hello', done: false }
console.log(hg.next());//{ value: { a: 'Generator' }, done: false }
console.log(hg.next());//{ value: undefined, done: true } 结束时 done 为true
复制代码
yield

其实 Generator 函数提供了一个可以暂停执行的函数,而 yield 语句则是暂停标志。

执行 next 方法时候运行的逻辑如下

  • 遇到 yield 就暂停执行后面的操作,并将紧跟在 yield 后面的表达式值作为返回对象的 value 属性值
  • 下一次调用 next 方法的时候,继续往下执行,直到遇到下一个 yield 语句
  • 如果没有遇到 yield 语句就一直执行,知道 return 语句为止,并将 return 后面的表达式值作为返回 value 值,如果没有就返回 undefined
next 方法参数
function* foo(x){
    // 执行next方法时传值进来 相当于 y = 所传的值
    var y = yield console.log(x + 1)
    // 执行next方法时传值进来 相当于 z = 所传的值
    var z = yield console.log(y + 1)
    return console.log(x,y,z)
}
var a = foo(5);
a.next(1);
a.next(2);
a.next(3);
//5 2 3
复制代码
可以使用 for...of 循环
function* get() {
    yield 0
    yield 1
    yield 2
    yield 3
    yield 4
}
for (let v of get()) {
    console.log(v) //0 1 2 3 4
}
复制代码
方法
  • throw() 遍历器对象上有一个 throw() 方法,可以再函数体外抛出错误,然后再函数体内捕获。
    var e = function* (){
        try {
            yield
        } catch (error) {   
            console.log('内部捕获', error)
        }
    }
    var i  = e();
    i.next();
    try {
        i.throw('a')
        i.throw('b')
    } catch (error) {
        console.log('外部捕获', error)
    }
    // 内部捕获 a
    // 外部捕获 b
    复制代码
  • return() 返回给定的值,并终结遍历。
yield* 语句

可以再 Generator 内部中调用另一个 Generator 函数。

function* a() {
    yield 2
    yield 3
}
function* b() {
    yield 1
    yield* a();
    yield 4
}
for (let v of b()) {
    console.log(v) //1 2 3 4
}
复制代码
Generator 的 this

Generator 函数总是返回一个遍历器,ES6 规定这个遍历器是 Generator 函数的实例,也继承了 Generator 函数的 prototype 对象上的方法。

function* F() {
    yield this.a = 1
    yield this.b = 2
    yield this.c = 3
}
F.prototype.hello = function(obj){
    console.log(this)
    console.log(this === obj)
    return "hi"
}
//如果把 F 当作普通的构造函数,并不会生效,因为 F 返回的总是遍历器对象,而不是 this 对象。
//F不是构造函数。 
let f = F()
f.hello(f)
//可以通过call方法绑定内部this
let f1 = F.call(F.prototype)
console.log(f1) //{}
f1.next()
console.log(f1.a) //1
f1.next()
console.log(f1.b) //2
f1.next()
console.log(f1.c) //3

//改造成构造函数
function F2() {
    return F.call(F.prototype)
}
let f2 = new F2()
console.log(f2) //{}
f2.next()
console.log(f2.a) //1
f2.next()
console.log(f2.b) //2
f2.next()
console.log(f2.c) //3
复制代码

Class

ES6 提供了 class 关键字来方便我们,让对象原型的写法更加清晰,更像面对对象编程的语法

const bar = Symbol('bar')
const sex = Symbol('sex')
class Student{
    /**
     * @param {*} age  年龄
     * @param {*} name 姓名
     */
    constructor(name){
        /** 
         * constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。
         * 一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
         */
        // this.age = age
        this.name = name
        // 单独调用会出现 this 指向不会指向当前实例,需要自己手动绑定/箭头函数声明函数/
        this.toString = this.toString.bind(this) 
    }
    toString(){
        //类 的方法 相当于 Student.prototype 不可枚举
        console.log(Student.classMethod())
        console.log(`name is ${this.name} \n${this.age} \n sex ${this[sex]}`)
        return (`name is ${this.name} \n${this.age} \n sex ${this[sex]}`)
    }
    set sex(value){
        this[bar](value)
    }
    get age(){
        return `age is ${this._age}`
    }
    set age(value){
        this._age = value
        // this.age = value
        console.log(`${value}`)
    }
    // 静态方法,不会被实例继承
    static classMethod() {
        // 如果静态方法包含this关键字,这个this指的是类,而不是实例。
        // 父类的静态方法,可以被子类继承。
        return '实例拿不到我';
    }
    // 私有方法和方法,通过 Symbol 来实现值的唯一性
    [bar](value){
        return this[sex] = value
    }
}

let xiayu = new Student("xiayu")
console.log(xiayu)
xiayu.age = 12
xiayu.sex = 'man'
console.log(xiayu.age) 
xiayu.toString()
var strF = xiayu.toString
strF()

// ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面 Parent.apply(this)。
// ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。
class Workers extends Student{
    constructor(name,job){
        // super关键字,它在这里表示父类的构造函数,用来新建父类的this对象。
        super(name) //必须调用父类的constructor
        this.job = job
    }
    toString(){
        return `job - ${this.job}` + super.toString()
    }
}

let block = new Workers('black','block')
block.age = 1
block.sex = 2
block.toString()
复制代码

转载于:https://juejin.im/post/5bd120aaf265da0abf7d2870

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值