JS高级之面试必须知道的几个点
深圳市人人聚财招前端啦 ~~~
招前端,招前端,招前端,欢迎扫码加群,砸简历过来:
前言
这段时间突然发现JS原生好多东西都忘记了,但有些东西确实很重要,所以又重新再梳理一次。主要有函数的3种定义方法,ES5函数this指向,call与appl用法,JS常见的4种设计模式,原型链,原型链和继承的方式(ES5和ES6)
1.函数的3种定义方法
1.1 函数声明
//ES5
function getSum(){}
function (){}//匿名函数
//ES6
()=>{}//如果{}内容只有一行{}和return关键字可省,
复制代码
1.2 函数表达式(函数字面量)
//ES5
var sum=function(){}
//ES6
let sum=()=>{}//如果{}内容只有一行{}和return关键字可省,
复制代码
1.3 构造函数
var sum=new GetSum(num1,num2)
复制代码
1.4 三种方法的对比
1.函数声明有预解析,而且函数声明的优先级高于变量;
2.使用Function构造函数定义函数的方式是一个函数表达式,这种方式会导致解析两次代码,影响性能。第一次解析常规的JavaScript代码,第二次解析传入构造函数的字符串
2.ES5中函数的4种调用
在ES5中函数内容的this指向和调用方法有关
2.1 函数调用模式
包括函数名()和匿名函数调用,this指向window
function getSum() {console.log(this) //window}getSum()(function() {console.log(this) //window})()var getSum=function() {console.log(this) //window}getSum()
复制代码
2.2 方法调用
对象.方法名(),this指向对象
var objList = {name: 'methods',getSum: function() {console.log(this) //objList对象}
}
objList.getSum()
复制代码
2.3 构造器调用
new 构造函数名(),this指向构造函数
function Person() {console.log(this); //指向构造函数Person
}
var personOne = new Person();
复制代码
2.4 间接调用
利用call和apply来实现,this就是call和apply对应的第一个参数,如果不传值或者第一个值为null,undefined时this指向window
function foo() {console.log(this);
}
foo.apply('我是apply改变的this值');//我是apply改变的this值
foo.call('我是call改变的this值');//我是call改变的this值
复制代码
3.ES6中函数的调用
箭头函数不可以当作构造函数使用,也就是不能用new命令实例化一个对象,否则会抛出一个错误
箭头函数的this是和定义时有关和调用无关
调用就是函数调用模式
(() => {console.log(this)//window
})()let arrowFun = () => {console.log(this)//window
}
arrowFun()let arrowObj = {arrFun: function() {(() => {console.log(this)//arrowObj})()}}arrowObj.arrFun();
复制代码
4.call,apply和bind
1.IE5之前不支持call和apply,bind是ES5出来的;
2.call和apply可以调用函数,改变this,实现继承和借用别的对象的方法;
4.1 call和apply定义
调用方法,用一个对象替换掉另一个对象(this)
对象.call(新this对象,实参1,实参2,实参3.....)
对象.apply(新this对象,[实参1,实参2,实参3.....])
4.2 call和apply用法
1.间接调用函数,改变作用域的this值
2.劫持其他对象的方法
var foo = {name:"张三",logName:function(){console.log(this.name);}
}
var bar={name:"李四"
};
foo.logName.call(bar);//李四
实质是call改变了foo的this指向为bar,并调用该函数
复制代码
3.两个函数实现继承
function Animal(name){ this.name = name; this.showName = function(){ console.log(this.name); }
}
function Cat(name){ Animal.call(this, name);
}
var cat = new Cat("Black Cat");
cat.showName(); //Black Cat
复制代码
4.为类数组(arguments和nodeList)添加数组方法push,pop
(function(){Array.prototype.push.call(arguments,'王五');console.log(arguments);//['张三','李四','王五']
})('张三','李四')
复制代码
5.合并数组
let arr1=[1,2,3];
let arr2=[4,5,6];
Array.prototype.push.apply(arr1,arr2); //将arr2合并到了arr1中
复制代码
6.求数组最大值
Math.max.apply(null,arr)
复制代码
7.判断字符类型
Object.prototype.toString.call({})
复制代码
4.3 bind
bind是function的一个函数扩展方法,bind以后代码重新绑定了func内部的this指向,不会调用方法,不兼容IE8
var name = '李四'var foo = {name: "张三",logName: function(age) {console.log(this.name, age);}}var fooNew = foo.logName;var fooNewBind = foo.logName.bind(foo);fooNew(10)//李四,10fooNewBind(11)//张三,11 因为bind改变了fooNewBind里面的this指向
复制代码
5.JS常见的四种设计模式
5.1 工厂模式
简单的工厂模式可以理解为解决多个相似的问题;
function CreatePerson(name,age,sex) {var obj = new Object();obj.name = name;obj.age = age;obj.sex = sex;obj.sayName = function(){return this.name;}return obj;
}
var p1 = new CreatePerson("longen",'28','男');
var p2 = new CreatePerson("tugenhua",'27','女');
console.log(p1.name); // longen
console.log(p1.age); // 28
console.log(p1.sex); // 男
console.log(p1.sayName()); // longenconsole.log(p2.name); // tugenhua
console.log(p2.age); // 27
console.log(p2.sex); // 女
console.log(p2.sayName()); // tugenhua
复制代码
5.2单例模式
只能被实例化(构造函数给实例添加属性与方法)一次
// 单体模式
var Singleton = function(name){this.name = name;
};
Singleton.prototype.getName = function(){return this.name;
}
// 获取实例对象
var getInstance = (function() {var instance = null;return function(name) {if(!instance) {//相当于一个一次性阀门,只能实例化一次instance = new Singleton(name);}return instance;}
})();
// 测试单体模式的实例,所以a===b
var a = getInstance("aa");
var b = getInstance("bb");
复制代码
5.3 沙箱模式
将一些函数放到自执行函数里面,但要用闭包暴露接口,用变量接收暴露的接口,再调用里面的值,否则无法使用里面的值
let sandboxModel=(function(){function sayName(){};function sayAge(){};return{sayName:sayName,sayAge:sayAge}
})()
复制代码
5.4 发布者订阅模式
就例如如我们关注了某一个公众号,然后他对应的有新的消息就会给你推送,
//发布者与订阅模式var shoeObj = {}; // 定义发布者shoeObj.list = []; // 缓存列表 存放订阅者回调函数// 增加订阅者shoeObj.listen = function(fn) {shoeObj.list.push(fn); // 订阅消息添加到缓存列表}// 发布消息shoeObj.trigger = function() {for (var i = 0, fn; fn = this.list[i++];) {fn.apply(this, arguments);//第一个参数只是改变fn的this,}}// 小红订阅如下消息shoeObj.listen(function(color, size) {console.log("颜色是:" + color);console.log("尺码是:" + size);});// 小花订阅如下消息shoeObj.listen(function(color, size) {console.log("再次打印颜色是:" + color);console.log("再次打印尺码是:" + size);});shoeObj.trigger("红色", 40);shoeObj.trigger("黑色", 42);
复制代码
代码实现逻辑是用数组存贮订阅者, 发布者回调函数里面通知的方式是遍历订阅者数组,并将发布者内容传入订阅者数组
更多设计模式请戳:Javascript常用的设计模式详解
6.原型链
6.1 定义
对象继承属性的一个链条
6.2构造函数,实例与原型对象的关系
var Person = function (name) { this.name = name; }//person是构造函数
var o3personTwo = new Person('personTwo')//personTwo是实例
复制代码
原型对象都有一个默认的constructor属性指向构造函数
6.3 创建实例的方法
1.字面量
let obj={'name':'张三'}
复制代码
2.Object构造函数创建
let Obj=new Object()
Obj.name='张三'
复制代码
3.使用工厂模式创建对象
function createPerson(name){var o = new Object();o.name = name;};return o;
}
var person1 = createPerson('张三');
复制代码
4.使用构造函数创建对象
function Person(name){this.name = name;
}
var person1 = new Person('张三');
复制代码
6.4 new运算符
1.创了一个新对象;
2.this指向构造函数;
3.构造函数有返回,会替换new出来的对象,如果没有就是new出来的对象
4.手动封装一个new运算符
var new2 = function (func) {var o = Object.create(func.prototype);    //创建对象var k = func.call(o);             //改变this指向,把结果付给kif (typeof k === 'object') {         //判断k的类型是不是对象return k;                  //是,返回k} else {return o;                  //不是返回返回构造函数的执行结果}
}
复制代码
更多详情:详谈JavaScript原型链
6.5 对象的原型链
7.继承的方式
JS是一门弱类型动态语言,封装和继承是他的两大特性
7.1原型链继承
将父类的实例作为子类的原型
1.代码实现
定义父类:
// 定义一个动物类
function Animal (name) {// 属性this.name = name || 'Animal';// 实例方法this.sleep = function(){console.log(this.name + '正在睡觉!');}
}
// 原型方法
Animal.prototype.eat = function(food) {console.log(this.name + '正在吃:' + food);
};
复制代码
子类:
function Cat(){
}
Cat.prototype = new Animal();
Cat.prototype.name = 'cat';// Test Code
var cat = new Cat();
console.log(cat.name);//cat
console.log(cat.eat('fish'));//cat正在吃:fish undefined
console.log(cat.sleep());//cat正在睡觉! undefined
console.log(cat instanceof Animal); //true
console.log(cat instanceof Cat); //true
复制代码
2.优缺点
简单易于实现,但是要想为子类新增属性和方法,必须要在new Animal()这样的语句之后执行,无法实现多继承
7.2 构造继承
实质是利用call来改变Cat中的this指向
1.代码实现
子类:
function Cat(name){Animal.call(this);this.name = name || 'Tom';
}
复制代码
2.优缺点
可以实现多继承,不能继承原型属性/方法
7.3 实例继承
为父类实例添加新特性,作为子类实例返回
1.代码实现
子类
function Cat(name){var instance = new Animal();instance.name = name || 'Tom';return instance;
}
复制代码
2.优缺点
不限制调用方式,但不能实现多继承
7.4 拷贝继承
将父类的属性和方法拷贝一份到子类中
1.子类:
function Cat(name){var animal = new Animal();for(var p in animal){Cat.prototype[p] = animal[p];}Cat.prototype.name = name || 'Tom';
}
复制代码
2.优缺点
支持多继承,但是效率低占用内存
7.5 组合继承
通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
1.子类:
function Cat(name){Animal.call(this);this.name = name || 'Tom';
}
Cat.prototype = new Animal();
Cat.prototype.constructor = Cat;
复制代码
7.6 寄生组合继承
function Cat(name){Animal.call(this);this.name = name || 'Tom';
}
(function(){// 创建一个没有实例方法的类var Super = function(){};Super.prototype = Animal.prototype;//将实例作为子类的原型Cat.prototype = new Super();
})();
复制代码
7.7 ES6的extends继承
ES6 的继承机制是先创造父类的实例对象this(所以必须先调用super方法),然后再用子类的构造函数修改this,链接描述
class ColorPoint extends Point {constructor(x, y, color) {super(x, y); // 调用父类的constructor(x, y)this.color = color;}toString() {return this.color + ' ' + super.toString(); // 调用父类的toString()}
}
复制代码
更多详情请戳:JS继承的实现方式
参考文献:
www.cnblogs.com/tugen...
www.cnblogs.com/humin...
www.cnblogs.com/cheng...
www.cnblogs.com/cheng...
JS高级之面试必须知道的几个点相关推荐
- 2018年中高级前端面试题目小结
2018年中高级前端面试题目小结 前言 关于前端面试,及面试题目,我之前有很多文章总结过,可以在右侧搜索面试,进行查找.其实面试中可以问的问题很多,最近几年,我也面试过很多工作2-4年的前端,我一般会 ...
- 【汇总】JS高级知识汇总
文章目录 前言 1.浏览器工作原理和V8引擎 2.JavaScript函数执行.作用域链以及内存管理 3.底层剖析JavaScript闭包执行以及内存模型.内存泄露 4.this的四个绑定规则及其细节 ...
- 《Ext JS 高级程序设计》的目录与样张
第一部分 Ext Core 第1 章 Ext Core 重要概念 ············· 2 1.1 Ext.Element······························· 2 1. ...
- 前端知识点总结——JS高级(持续更新中)
前端知识点总结--JS高级(持续更新中) 1.字符串 什么是: 连续存储多个字符的字符数组 相同: 1. 下标 2. .length 3. 遍历 4. 选取: slice(starti[, endi] ...
- Ext JS高级程序设计
Ext JS高级程序设计 图书详细情况查看: http://www.china-pub.com/193076 市场价 :¥59.00 会员价 : ¥44.25(75折) [作 者]黄灯桥;徐会生 [同 ...
- 高级 Java 面试通关知识点整理
转载自 高级 Java 面试通关知识点整理 1.常用设计模式 单例模式:懒汉式.饿汉式.双重校验锁.静态加载,内部类加载.枚举类加载.保证一个类仅有一个实例,并提供一个访问它的全局访问点. 代理模式: ...
- Js高级(1) 事件11.30
JS高级(1) 1.事件 概念:浏览器客户端上客户触发的行为都称为事件,所有的事件都是天生自带的,不需要我们去绑定,只需要我们去触发.通过obj.事件名=function(){} 事件名:onmous ...
- 互联网高级Java面试总结
前不久刚换了单位,这段时间抽出时间来总结一下. 本人渣本毕业四年,无大厂工作经验,出来面高级Java. 上家单位是一个知名互联网平台,但是体量不大的小公司(5线互联网公司),但就是出名(职场人都知道~ ...
- JS高级的学习(二)
JS高级的学习(二) set对象 Set 是一个对象 存放数据 数据永远不会重复 Set 当成是一个数组 遍历 使用 数组方法 find findIndex Map 数组转成 Set对象 const ...
最新文章
- web.config配置
- 调用settings中的常数
- 提取文件出错_提取中文、英文和数字,其实很简单
- 面试官出的MySQL索引问题,这篇文章全给你解决!
- PHP之MVC项目实战(三)
- 109. 有序链表转换二叉搜索树
- Android第三方开源水面波浪波形view:WaveView(电量、能量、容量指示)
- C++常用的图像像素值读写的方法
- 热门编程语言间的差异
- pcb外观维修_5种最常见的PCB维修
- 计算机软考深圳积分,2020年软考证书能为深圳积分入户加分吗?
- 0602 信用卡防盗刷学习总结
- android补间动画有哪几种,Android补间动画、属性动画 常用功能总结
- Ubuntu虚拟机使用桥接网络设置静态IP
- 苹果、google、微软的那些事(iPhone)
- Java通过freemaker实现健康报告生成(包含列表、列表合并列)
- 四种常用聚类及代码(三):birch(一种层次聚类)
- 微信可以改彩色昵称了!!!太sao了吧!
- DNS域名解析问题排查
- Tesla Bot 特斯拉机器人介绍