一些关于JS的基础知识巩固复习、整理
学了忘 忘了学。。。
一 instanceof
instanceof 运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
1 | arr = [1,2,3] | 
2 | arr instanceof Array   | 
3 | // true  因为 arr.__proto__ === Array.prototype | 
4 | arr instanceof Object   | 
5 | // true  因为 arr.__proto__.__proto__ === Object.prototype | 
一般情况下instanceof 不能判断基本类型
1 | 'abc' instanceof String   // false | 
2 | 123 instanceof Number     // false | 
3 | true instanceof Boolean   // false | 
自己实现 instanceof
1 | const myInstanceof = function(instance, constructor){ | 
2 |   // 如果是基本类型就返回false 用 typeof 判断 | 
3 |   if(typeof instance !== 'object' && typeof instance !== 'function' || instance === null){ | 
4 |     return false | 
5 |   } | 
6 | |
7 |   let proto = instance.__proto__    | 
8 |   // 或者 proto = Object.getPrototypeOf(instance) | 
9 | |
10 |   while(proto !== null){   // 因为原型链的终点是 null | 
11 |     if(proto === constructor.prototype) return true  | 
12 |     proto = proto.__proto__ | 
13 |   } | 
14 |   return false | 
15 | |
16 |   // 或者直接用isPrototypeOf判断 | 
17 |   // return constructor.prototype.isPrototypeOf(instance) | 
18 | } | 
测试一下
1 | myInstanceof(123,Object)         // false | 
2 | myInstanceof('abc',String)       // false | 
3 | myInstanceof([],Array)           // true | 
4 | myInstanceof([],Object)          // true | 
5 | myInstanceof({},Array)           // false | 
6 | myInstanceof({},Object)          // true | 
7 | myInstanceof(Math.max,Function)  // true | 
二 call bind apply的区别
这三个方法都是在函数的原型链上的方法,作用是用来改变this指向
这三个函数的第一个参数都是指定this
call方法
1 | // 通过数组的方法将类数组转为数组avascript | 
2 | let arr3 = {0:1,1:0,2:3,3:2,length:4} | 
3 | Array.prototype.slice.call(arr3)  // 这样arr3本来没有slice方法 现在也可以使用了 | 
apply方法
apply() 方法调用一个具有给定this值的函数,以及以一个数组(或类数组对象)的形式提供的参数。
appyl与call的区别
- call的第二个参数传的是参数列表
 - apply的第二个参数传的的数组
 
1 | // 求最大值 | 
2 | Math.max(1,3,4,2)  // 4 | 
3 | Math.max.call(null,1,3,2,4) | 
4 | Math.max.apply(null,[1,3,2,4])  // 这样可以直接求数组中的最大值 | 
bind方法
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
bind改变this指向后不会立即调用 而是返回一个yongq8
1 | let obj = { | 
2 |   say(){ | 
3 |     console.log(this) | 
4 |   } | 
5 | } | 
6 | setTimeout(obj.say,1000)   // 调用的时候打印的this是window,1000) | 
7 | // 我们可以通过bind绑定this | 
8 | setTimeout(obj.say.bind(obj),2000)   // 打印的时候是obj | 
9 | |
10 | const fn = function(){ | 
11 |   console.log(this.name) | 
12 | } | 
13 | let obj = { | 
14 |   name: 'obj 的name' | 
15 | } | 
16 | let objFn = fn.bind(obj) | 
17 | objFn()  // 'obj'的name | 
三 Object.defineProperty
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
对象数据属性默认有四个特性
- value 值 默认为undefined
 - configurable (是否可修改描述符对象 是否能通过delete删除属性 默认为false)
 - enumerable (是否可被遍历 默认为false)
 - writable (是否可改变 默认为false)
 
对象访问器属性 不包含数据值 有四个特性:
- Configurable
 - Enumerable
 - Get
 - Set
 
要修改属性的默认特性,必须使用Object.defineProperty()方法 接受三个参数: 属性所在的对象 属性的名字 一个描述符对象
1 | const object = {}; | 
2 | |
3 | Object.defineProperty(object, 'property1', { | 
4 |   value: 42, | 
5 |   writable: false,      // 值不可变 | 
6 |   configurable: true,   // 可以被修改 可以被delete | 
7 |   enumerable: false | 
8 | }) | 
9 | |
10 | object.property1 = 77   // throws an error in strict mode | 
11 | console.log(object.property1)  // 42 因为该属性的值是不可改变的 | 
12 | |
13 | Object.defineProperty(object, 'property1', { | 
14 |   value: 42, | 
15 |   writable: true,      // 重新修改为值可变 | 
16 | }) | 
17 | |
18 | object.property1 = 77 | 
19 | console.log(object.property1)   // 77 现在值是可变的 | 
20 | |
21 | delete object.property1   // true 可以被删除 | 
22 | |
23 | Object.defineProperty(object,'property2',{ | 
24 |   value: 55, | 
25 |   enumerable: true | 
26 | }) | 
27 | |
28 | // 可被遍历的属性 | 
29 | Object.keys(object)   // ['property2'] 因为property2的enumerable是true | 
30 | for(let key in object) { | 
31 |   console.log(key)       // 'property2'  只有一个属性可被遍历到 | 
32 | } | 
33 | |
34 | Object.property2 = 77  // throws an error in strict mode | 
35 | console.log(Object.property2)  // 55 默认就是不可变的 | 
36 | |
37 | Object.defineProperty(object,'property2',{ | 
38 |   writable: true | 
39 | })   // 报错 因为 configurable 默认为false 不可再重新定义描述符对象 | 
40 |   | 
41 | delete object.property2  // false configurable 默认为false 属性不可被删除 | 
定义访问器属性
1 | var book = { | 
2 |    _year: 2004, | 
3 |    edition: 1 | 
4 | } | 
5 | |
6 | Object.defineProperty(book,'year',{ | 
7 |   get: function(){ | 
8 |     return this._year | 
9 |   }, | 
10 |   set: function(newValue){ | 
11 |     if(newValue){ | 
12 |       this._year = newValue | 
13 |       this.edition += newValue - 2004 | 
14 |     } | 
15 |   } | 
16 | }) | 
17 | // {_year: 2004, edition: 1} | 
18 | book.year = 2005  // 2005 | 
19 | book.edition      // 2 | 
定义多个属性时可以用 Object.defineProperties方法
1 | var obj = {}; | 
2 | Object.defineProperties(obj, { | 
3 |   'property1': { | 
4 |     value: true, | 
5 |     writable: true | 
6 |   }, | 
7 |   'property2': { | 
8 |     value: 'Hello', | 
9 |     writable: false | 
10 |   } | 
11 |   // etc. etc. | 
12 | }) | 
四 Object.getOwnPropertyDescriptor
Object.getOwnPropertyDescriptor()方法可以读取属性的描述符
1 | Object.getOwnPropertyDescriptor(object,'property1') | 
同理 Object.getOwnPropertyDescriptors()方法用来获取一个对象的所有自身属性的描述符