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