视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
一些你可能不熟悉的JS知识点总结
2020-11-27 21:59:53 责编:小采
文档


具体函数细节:

Reflect.apply(target, this, arguments)

// target:目标函数
// this:绑定的上下文对象
// arguments:函数的参数列表
Reflect.apply(target, this, arguments)

const arr = [2, 3, 4, 5, 6];
let max;
// ES6
max = Reflect.apply(Math.max, null, arr)

// ES5 
max = Math.max.apply(null, arr);
max = Function.prototype.apply.call(Math.max, null, arr);

Reflect.construct(target, argumentsList[, newTarget])

// 这个方法,提供了一种新的不使用new来调用构造函数的方法
function A(name) {
 console.log('Function A is invoked!');
 this.name = name;
}
A.prototype.getName = function() {
 return this.name;
};

function B(age) {
 console.log('Function B is invoked!');
 this.age = age;
}
B.prototype.getAge = function() {
 return this.age;
};


// 测试 (这两种是一致的)
var tom = new A('tom');
var tom = Reflect.construct(A, ['tom']);


// jnney继承了A的实例属性,同时继承了B的共享属性
// 简单来说,A构造函数被调用,但是 jnney.__proto__ === B.prototype
var jnney = Reflect.construct(A, ['jnney'], B);

Reflect.defineProperty(target, propertyKey, attributes)

这个方法和Object.definePropperty(属性定义失败,会抛出一个错误,成功则返回该对象)相似,不过Reflect.defineProperty(属性定义失败,返回false,成功则返回true)返回的是一个Boolean值。

let obj = {};

let obj1 = Object.defineProperty(obj, 'name', {
 enumerable: true,
 value: 'bjw' 
});

// 这里会返回false 因为我们上面定义name这个属性是不可修改的,
// 然后我们又在这里修改了name属性,所以修改失败返回值为false
let result1 = Reflect.defineProperty(obj, 'name', {
 configurable: true,
 enumerable: true,
 value: 'happy'
});
console.log(result1); // false

Reflect.deleteProperty(target, propertyKey)

let obj = {
 name: 'dreamapple',
 age: 22
};

let r1 = Reflect.deleteProperty(obj, 'name');
console.log(r1); // true
let r2 = Reflect.deleteProperty(obj, 'name');
console.log(r2); // true
let r3 = Reflect.deleteProperty(Object.freeze(obj), 'age');
console.log(r3); // false

Reflect.get(target, propertyKey[, receiver])

Reflect.set(target, propertyKey, value[, receiver])

这个方法用来读取/设置一个对象的属性,target是目标对象,propertyKey是我们要读取的属性,receiver是可选的,如果propertyKeygetter函数里面有this值,那么receiver就是这个this所代表的上下文。

Reflect.getOwnPropertyDescriptor(target, propertyKey)

这个方法与Object.getOwnPropertyDescriptor方法类似,其中target是目标对象,propertyKey是对象的属性,如果这个属性存在属性描述符的话就返回这个属性描述符;如果不存在的话,就返回undefined。(如果第一个参数不是对象的话,那么Object.getOwnPropertyDescriptor会将这个参数强制转换为对象,而方法 Reflect.getOwnPropertyDescriptor会抛出一个错误。)

var obj = {age: 22}
Reflect.getOwnPropertyDescriptor(obj, 'age')
{value: 22, writable: true, enumerable: true, configurable: true}

Reflect.getPrototypeOf(target)

Reflect.setPrototypeOf(target, prototype)

这个方法与Object.getPrototypeOf方法是一样的,都是返回一个对象的原型,也就是内部的[[Prototype]]属性的值。

Reflect.setPrototypeOfObject.setPrototypeOf方法的作用是相似的,设置一个对象的原型,如果设置成功的话,这个对象会返回一个true;如果设置失败,这个对象会返回一个false。

Reflect.has(target, propertyKey)

这个方法相当于ES5的in操作符,就是检查一个对象上是否含有特定的属性;我们继续来实践这个方法:

function A(name) {
 this.name = name || 'dreamapple';
}
A.prototype.getName = function() {
 return this.name;
};

var a = new A();

console.log('name' in a); // true
console.log('getName' in a); // true

let r1 = Reflect.has(a, 'name');
let r2 = Reflect.has(a, 'getName');
console.log(r1, r2); // true true

Reflect.isExtensible(target)

这个函数检查一个对象是否是可以扩展的,也就是是否可以添加新的属性。(要求target必须为一个对象,否则会抛出错误)

let obj = {};
let r1 = Reflect.isExtensible(obj);
console.log(r1); // true
// 密封这个对象
Object.seal(obj);
let r2 = Reflect.isExtensible(obj);
console.log(r2); // false

模块化

使用模块化,可以为我们带来以下好处:

  • 解决命名冲突
  • 提供复用性
  • 提高代码可维护性
  • 立即执行函数

    在早期,使用立即执行函数实现模块化,通过函数作用域解决了命名冲突、污染全局作用域的问题。

    AMD 和 CMD

    这两种实现方式已经很少见到,具体的使用方式如下:

    // AMD
    define(['./a', './b'],function(a, b){
     // 模块加载完毕可以使用
     a.do();
     b.do(); 
    });
    
    // CMD
    define(function(require, exports, module){
     // 加载模块
     var a = require('./a'); 
    });

    CommonJS

    CommonJS最早是Node在使用,目前可以在Webpack中见到它。

    // a.js
    module.exports = {
     a: 1
    }
    
    // or 
    exports.a = 1;
    
    // 在b.js中可以引入
    var module = require('./a');
    module.a // log 1

    难点解析:

    // module 基本实现
    var module = {
     id: 'xxx',
     exports: {}
    }
    
    var exports = module.exports;
    // 所以,通过对exports重新赋值,不能导出变量

    ES Module

    ES Module 是原生实现模块化方案。

    // 导入模块
    import xxx form './a.js';
    import { xxx } from './b.js';
    
    // 导出模块
    export function a(){}
    
    // 默认导出
    export default {};
    export default function(){}
    

    ES Module和CommonJS区别

  • CommonJS支持动态导入,也就是require(${path}/xx.js),ES Module不支持
  • CommonJS是同步导入,因为用于服务器端,文件都在本地,同步导入即使卡住主线程影响也不大。而ES Module是异步导入,因为用于浏览器,需要下载文件,采用同步导入会对渲染有很大影响
  • CommonJS在导出时都是值拷贝,就算导出值变了,导入的值也不会改变。如果想更新值,必须重新导入一次。但是ES Module采用实时绑定的方式,导入导出的值都指向同一个内存地址,所以导入值会跟导出值变化
  • ES Module 会编译成 require/exports 来执行的
  • 手写简单版本的Promise

    const PENDING = 'pending';
    const RESOLVED = 'resolved';
    const REJECTED = 'rejected';
    
    function MyPromise(fn) {
     const _this = this;
     _this.state = PENDING;
     _this.value = null;
     _this.resolvedCallbacks = [];
     _this.rejectedCallbacks = [];
    
    
     // resolve函数
     function resolve(value) {
     if (_this.state === PENDING) {
     _this.state = RESOLVED;
     _this.value = value;
     _this.resolvedCallbacks.map(cb => cb(_this.value));
     }
     }
    
     // rejected函数
     function reject(value) {
     if (_this.state === PENDING) {
     _this.state = REJECTED;
     _this.value = value;
     _this.rejectedCallbacks.map(cb => cb(_this.value));
     }
     }
    
     // 当创建对象的时候,执行传进来的执行器函数
     // 并且传递resolve和reject函数
     try {
     fn(resolve, reject);
     } catch (e) {
     reject(e);
     }
    }
    
    // 为Promise原型链上添加then函数
    MyPromise.prototype.then = function (onFulfilled, onRejected) {
     const _this = this;
     onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : v => v;
     onRejected = typeof onRejected === 'function' ? onRejected : r => {
     throw r;
     }
     if (_this.state === PENDING) {
     _this.resolvedCallbacks.push(onFulfilled);
     _this.rejectedCallbacks.push(onRejected);
     }
     if (_this.state === RESOLVED) {
     onFulfilled(_this.value);
     }
     if (_this.state === REJECTED) {
     onRejected(_this.value);
     }
     return _this;
    }
    
    
    
    // 测试
    new MyPromise(function (resolve, reject) {
     setTimeout(() => {
     resolve('hello');
     }, 2000);
    }).then(v => {
     console.log(v);
    }).then(v => {
     console.log(v + "1");
    })

    这篇文章就介绍到这了,需要的朋友可以参考一下。

    下载本文
    显示全文
    专题