撩课-Web大前端每天5道面试题-Day17
1.apply, call和bind有什么区别?
三者都可以把一个函数应用到其他对象上,注意不是自身对象. apply,call是直接执行函数调用,bind是绑定,执行需要再次调用. apply和call的区别是apply接受数组作为参数,而call是接受逗号分隔的无限多个参数列表. 代码如下: function Person() { } Person.prototype.sayName() { alert(this.name); } var obj = {name: 'michaelqin'}; // 注意这是一个普通对象,它不是Person的实例 1) apply Person.prototype.sayName.apply(obj, [param1, param2, param3]); 2) call Person.prototype.sayName.call(obj, param1, param2, param3); 3) bind var liaoke = Person.prototype.sayName.bind(obj); liaoke ([param1, param2, param3]); // bind需要先绑定,再执行 liaoke (param1, param2, param3); // bind需要先绑定,再执行
2.defineProperty, hasOwnProperty, isEnumerable都是做什么用的?
Object.defineProperty(obj, prop, descriptor)用来给对象定义属性, 有value,writable,configurable,enumerable,set/get等.hasOwnProerty用于检查某一属性是不是存在于对象本身,继承来的父亲的属性不算. isEnumerable用来检测某一属性是否可遍历,也就是能不能用for..in循环来取到.
3. js常用设计模式的实现思路,单例,工厂,代理,装饰,观察者模式等?
1) 单例: 任意对象都是单例,无须特别处理 var obj = {name: 'michaelqin', age: 30}; 2) 工厂: 就是同样形式参数返回不同的实例 function Person() { this.name = 'Person1'; } function Animal() { this.name = 'Animal1'; } function Factory() {} Factory.prototype.getInstance = function(className) { return eval('new ' + className + '()'); } var factory = new Factory(); var obj1 = factory.getInstance('Person'); var obj2 = factory.getInstance('Animal'); console.log(obj1.name); // Person1 console.log(obj2.name); // Animal1 3) 代理: 就是新建个类调用老类的接口,包一下 function Person() { } Person.prototype.sayName = function() { console.log('michaelqin'); } Person.prototype.sayAge = function() { console.log(30); } function PersonProxy() { this.person = new Person(); var that = this; this.callMethod = function(functionName) { console.log('before proxy:', functionName); that.person[functionName](); // 代理 console.log('after proxy:', functionName); } } var pp = new PersonProxy(); pp.callMethod('sayName'); // 代理调用Person的方法sayName() pp.callMethod('sayAge'); // 代理调用Person的方法sayAge() 4) 观察者: 就是事件模式,比如按钮的onclick这样的应用. function Publisher() { this.listeners = []; } Publisher.prototype = { 'addListener': function(listener) { this.listeners.push(listener); }, 'removeListener': function(listener) { delete this.listeners[listener]; }, 'notify': function(obj) { for(var i = 0; i < this.listeners.length; i++) { var listener = this.listeners[i]; if (typeof listener !== 'undefined') { listener.process(obj); } } } }; // 发布者 function Subscriber() { } Subscriber.prototype = { 'process': function(obj) { console.log(obj); } }; // 订阅者 var publisher = new Publisher(); publisher.addListener(new Subscriber()); publisher.addListener(new Subscriber()); publisher.notify({name: 'michaelqin', ageo: 30}); // 发布一个对象到所有订阅者 publisher.notify('2 subscribers will both perform process'); // 发布一个字符串到所有订阅者
4.promise只有2个状态,成功和失败,怎么让一个函数无论成功还是失败都能被调用?
使用promise.all() Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。 Promise.all方法接受一个数组作为参数,数组里的元素都是Promise对象的实例, 如果不是,就会先调用下面讲到的Promise.resolve方法,将参数转为Promise实例,再进一步处理。 (Promise.all方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是Promise实例。) 示例: var p =Promise.all([p1,p2,p3]); p的状态由p1、p2、p3决定,分为两种情况。 当该数组里的所有Promise实例都进入Fulfilled状态:Promise.all**返回的实例才会变成Fulfilled状态。 并将Promise实例数组的所有返回值组成一个数组,传递给Promise.all返回实例的回调函数**。 当该数组里的某个Promise实例都进入Rejected状态: Promise.all返回的实例会立即变成Rejected状态。 并将第一个rejected的实例返回值传递给Promise.all返回实例的回调函数。
5.说说字符串常用的十个函数?
charAt() 返回在指定位置的字符。
concat() 连接字符串。
fromCharCode() 从字符编码创建一个字符串。
indexOf() 检索字符串。
match() 找到一个或多个正则表达式的匹配。
replace() 替换与正则表达式匹配的子串。
search() 检索与正则表达式相匹配的值。
slice() 提取字符串的片断,并在新的字符串中返回被提取的部分。
split() 把字符串分割为字符串数组。
substr() 从起始索引号提取字符串中指定数目的字符。
substring() 提取字符串中两个指定的索引号之间的字符。
toLocaleLowerCase() 把字符串转换为小写。
toLocaleUpperCase() 把字符串转换为大写。
toLowerCase() 把字符串转换为小写。
toUpperCase() 把字符串转换为大写。
toString() 返回字符串。
valueOf() 返回某个字符串对象的原始值。