《前端之路》之 JavaScript 高级技巧、高阶函数(一)

目录 一、高级函数 1-1 安全的类型检测 1-2 作用域安全的构造函数 1-3 惰性载入函数 1-4 函数绑定 1-5 函数柯里化 1-6 反函数柯里化 一、高级函数 1-1 安全的类型检测 想到类型检测,那么脑海里第一反应应该就是在 Javascript 的世界中到底有哪些类型(这真的是一个非常古老的问题了) 我们大致分为 2 类: 基本类型 和 引用类型 其中 基本类型 包括了: string、number、bool、undefined、null 其中 引用类型 包括了: Array、Function、Object 那我们用 type 和 instanceof 分别来看下这几种数据类型判定返回的内容 为什么说 利用 type 和 instanceof 是不安全的类型检测 const str = 'test' const num = 12 const bool = false const unde = undefined const nulls = null const Array = [1,2,3,4] const Object = {name: 'zzz'} const checkType = (type) => { return typeof(type) } // 使用 type 来判断 console.log(checkType(str)) // string console.log(checkType(num)) // number console.log(checkType(bool)) // boolean console.log(checkType(unde)) // undefined console.log(checkType(nulls)) // object console.log(checkType(Array)) // object console.log(checkType(Object)) // object // 很显然 null、Array、Object 返回的都是 object 不够安全 ( bug 点 ) // 用 instanceof 来判断 const checkInstance = (type) => { return type instanceof String } console.log(checkInstance(str)) // 是 false 这是为什么呢? // 那么我们就需要来介绍下 instanceof 的原理了。 1-1-1 instanceof 的原理 instanceof 的的功能实现是 前者是否为后者的实例 , 具体的代码就是: eg: let res = a instanceof A // a 是 A 的实例 // A 是 a 的构造函数 // 同时 a 的 __proto__ == A 的 prototype 那么 a instanceof A == true 否则就等于 false 其中 有几个关键的点 如下: 关于 constrcutor 、proto 、prototype、原型对象 这四个点的理解。 推荐一篇好文章吧 prototype、proto、constructor 的三角关系 回到上面 a.__proto__ 指向的就是 a 的原型对象 A.prototype 指向的是 实例对象 的 原型对象 var Foo = function() { this.setName = (name) => { this.name = name } } var foo = new Foo Foo.prototype 指向 => 原型对象(理解为公共对象) // 通过同一个构造函数实例化的多个对象具有相同的原型对象。经常使用原型对象来实现继承 Foo.prototype.constructor 指向 => 构造函数本身(Foo) foo.__proto__ 指向 => 原型对象(理解为公共对象) foo.constructor 指向 => 构造函数 (Foo) 1-2 作用域安全的构造函数 在全局作用域内调用函数构造函数,由于没有使用new,导致在全局作用域添加冗余的属性 function Person(name,job) { this.name = name this.job = job } // 假如为使用 New 操作 var person = Person('zhangsan','sell') console.log(window.name, window.job) // zhangsan sell console.log(person.name, person.job) // VM76:11 Uncaught TypeErrorr 这个问题是由this对象的晚绑定造成的 因此,需要在函数里面确认 this对象是正确类型的实例: function Person(name){ if(this instanceof Person){ this.name = 'zhang'; } else { return new Person(name) } } var person = Person('zhang') console.log(window.name) // '' console.log(person.name) // zhang 1-3 惰性载入函数 惰性载入表示函数执行的分支会在函数第一次调用的时候执行,在第一次调用过程中,该函数会被覆盖为另一个按照合适方式执行的函数,这样任何对原函数的调用就不用再经过执行的分支去进行判断了。(节约算力) 1-3-1 应用场景 1、 AJAX 在不同浏览器下兼容性 2、 APP 内嵌 H5 不同环境下同一种功能方法,写法不一样 3、 H5 在不同平台下多处表现形式因为一个方法而展现的不一样。 1-3-2 注意的地方 1、应用越频繁,越能体现这种模式的优势所在 2、固定不变,一次判定,在固定的应用环境中不会改变 3、复杂的分支判断,没有差异性,不需要应用这种模式 1-3-3 Demo const getCurEnv = () => { // 当前环境为 chrome 浏览器环境 return window.navigator.userAgent.toLowerCase().match(/chrome/i) !== null } const Person = function(name) { this.name = name } const http = { created: function() { if (getCurEnv()) { console.log(this) this.created = function() { console.log('test1') return new Person('zhang1') } console.log('test2') return new Person('zhang2') } else { this.created = function() { console.log('test3') return new Person('zhang3') } } }, Atest: ()=> { console.log(this) // window {} }, Ftest: function() { console.log(this) // http {} } } http.created() // test2 Person {name: "zhang2"} http.created() // test1 Person {name: "zhang1"} // 实际有效的 惰性载入函数 上面的 二个 方法返回的值 其实是一样的。这样惰性载入函数 才是真实有效。 1-4 函数绑定 这个技巧常常和回调函数与事件处理一起使用,以便在将函数作为变量传递的同时保留代码执行环境 很多JavaScript库实现了一个可以将函数绑定到指定环境的函数,这个函数一般都叫做bind()。一个简单的bind()函数接受一个函数和一个环境,并返回一个给的环境中调用给定函数的函数,并且将所有参数原封不动传递过去。这个函数返回的是一个闭包。 上面的语言描述总是很虚无飘渺,我们来直接上Demo: 1-4-1 Demo var obj1 = { name: 'zhang', getName: function() { console.log(arguments[0][2], 'obj1') return this.name } } var obj2 = { name: 'lisi', getName: function() { console.log(arguments, 'obj2') return this.name } } function Bind(fn, context) { return fn.call(context, arguments) } Bind(obj1.getName,obj2,'xxxxx') // Arguments [Arguments(3), callee: ƒ, Symbol(Symbol.iterator): ƒ] "obj1" // 'lisi' // 这里我们对于 arguments 的 理解和操作来说都是比较陌生,那么下面 我们再来介绍下 // arguments 具体是什么。 1-4-2 arguments 类数组 (Array-like) 可以用下标访问每个元素 有 length 属性 arguments 的数据类型为 object 可以使用 for 和 for-in 方法 不具备 Array 原生方法 Demo var test = function() { console.log(arguments) console.log(arguments[0]) console.log(arguments.length) console.log(typeof arguments) for(var i = 0; i
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信