JS高级之面试必须知道的几个点
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)//李四,10
fooNewBind(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()); // longen
console.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指向,把结果付给k
if (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高级之面试必须知道的几个点的更多相关文章
- JS高级前端开发群加群说明及如何晋级
JS高级前端开发群加群说明 一.文章背景: 二. 高级群: 三. 加入方式: 四. 说明: 一.文章背景: 去年年初建了几个群,在不经意间火了,一直排在“前端开发”关键字搜索结果第一名.当然取得这 ...
- 前端进阶试题css(来自js高级前端开发---豪情)既然被发现了HOHO,那我就置顶了嘿嘿!觉得自己技术OK的可以把这套题目做完哦,然后加入高级前端的社区咯
http://www.cnblogs.com/jikey/p/4426105.html js高级前端开发加群方法(此群很难进,里面纯技术,严禁广告,水群) 完整题目做完发邮箱(jikeytang@16 ...
- Node.js高级编程读书笔记Outline
Motivation 世俗一把,看看前端的JavaScript究竟能做什么. 顺便检验一下自己的学习能力. Audience 想看偏后台的Java程序员关于前端JavaScript的认识的职业前端工程 ...
- 读JS高级——第五章-引用类型 _记录
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定
js高级程序设计笔记之-addEventListener()与removeEventListener(),事件解除与绑定 addEventListener()与removeEventListener( ...
- 《JS高级程序设计》笔记 —— 解析查询字符串
今天在继续翻阅<JS高级程序设计>的时候,正好翻到location对象这一小节,其中有一部分就是讲的解析查询字符串.看到这个内容立马想到了做去哪儿秋招笔试题的时候有这么一道题. 去哪儿笔试 ...
- js 高级函数 之示例
js 高级函数作用域安全构造函数 function Person(name, age) { this.name = name; this.age = age; ...
- 惰性函数——JS高级
我们先来看一下js的异步提交. XHR我们在原生的时候常常用到,因为常用到,我们更多把封装到了工具库中 先看下他最常用的实现 // 旧方法 function createXHR() { var xhr ...
- 《Node.js 高级编程》简介与第二章笔记
<Node.js 高级编程> 作者简介 Pedro Teixerra 高产,开源项目程序员 Node 社区活跃成员,Node公司的创始人之一. 10岁开始编程,Visual Basic.C ...
随机推荐
- python学习笔记03:python的核心数据类型
从根本上讲,Python是一种面向对象的语言.它的类模块支持多态,操作符重载和多重继承等高级概念,并且以Python特有的简洁的语法和类型,OOP十分易于使用.Python的语法简单,容易上手. Py ...
- <Effective C++>读书摘要--Designs and Declarations<三>
<Item 22> Declare data members private 1.使数据成员private,保持了语法的一致性,client不会为访问一个数据成员是否需要使用括号进行函数调 ...
- udp->ip & tcp->ip 发送数据包的目的地址的源地址是什么时候确定的?
udp->ip & tcp->ip udp到ip层是:ip_send_skb tcp到ip层是: ip_queue_xmit 拿tcp为例,在使用[ip_queue_xmit, i ...
- [剑指Offer] 48.不用加减乘除做加法
题目描述 写一个函数,求两个整数之和,要求在函数体内不得使用+.-.*./四则运算符号. [思路] 首先看十进制是如何做的: 5+7=12,三步走第一步:相加各位的值,不算进位,得到2.第二步:计算进 ...
- Visual Stdio 2015打包安装项目的方法(使用Visual Studio Installer)
首先在官网下载VS2015的Visual Studio Installer 1.创建安装项目 里面最左侧的框框有三个文件夹 1.“应用程序文件夹”即"Application Folder&q ...
- BZOJ 1486 最小圈(01分数规划)
好像是很normal的01分数规划题.最小比率生成环. u(c)=sigma(E)/k.转化一下就是k*u(c)=sigma(E). sigma(E-u(c))=0. 所以答案对于这个式子是有单调性的 ...
- bzoj4502 串
题意:给你n(n<=10000)个字符串,每个字符串的长度不超过30,可以选择两个非空前缀把它们拼起来得到一个字符串(这两个前缀可以来自同一个字符串,也可以是同一个字符串的同一个非空前缀),问得 ...
- 【bzoj3672】[Noi2014]购票 斜率优化dp+CDQ分治+树的点分治
题目描述 给出一棵以1为根的带边权有根树,对于每个根节点以外的点$v$,如果它与其某个祖先$a$的距离$d$不超过$l_v$,则可以花费$p_vd+q_v$的代价从$v$到$a$.问从每个点到1花费 ...
- openstack之Glance介绍
什么是Glance glance即image service(镜像服务),是为虚拟机的创建提供镜像服务 为什么要有Glance 我们基于openstack是构建基本的Iaas平台对外提供虚机,而虚机在 ...
- [LOJ #6433]「PKUSC2018」最大前缀和
题目大意:给你一个$n(n\leqslant20)$项的数列$A$,设重排后的数列为$A'$,令$pre_p=\sum\limits_{i=1}^pA'_i$,求$max\{pre_i\}$的期望,乘 ...