javascript
学习原型链之前我们先认识一下构造函数,代码如下:
function S() {
this.name = 'xxx';
this.say = function() { console.log(this.name) }
}
var s1 = new S();
其中,s1是S的实例,s1的__proto__(大家先不用管__proto__属性,后续会讲到)中有一个constructor(构造函数)属性,该属性指向S。
在这里,大家可以记住两点:
1.s1是构造函数S的实例;
2.s1.__proto__.constructor===S 也可以写成 s1.constructor===S;
接下来我们来看下一段代码:
function S2() {}
S2.prototype.name = 'XXX';
S2.prototype.say = function() {
console.log(this.name);
}
var s2 = new S2();
var s3 = new S2();
console.log(s2.sayName === s3.sayName);//true
console.log(s2.__proto__===S2.prototype);//true
这一段代码中我们可以看到一个新属性——prototype,这是什么呢,其实这就是构造函数S2的原型对象,每个对象都有__proto__属性,但是只有函数对象才有prototype属性。而s2是构造函数S2的实例,而s2.__proto__指向的就是S2的原型对象,即s2.__proto__===S2.prototype。得到一个结论,实例的__proto__属性指向的就是其构造函数的原型对象。
继续上一步的代码,我们添加代码继续调试:
console.log(s2.__proto__);//返回S2的原型对象
console.log(S2.prototype);//返回S2的原型对象
console.log(s2.__proto__.__proto__);//返回Object对象
console.log(S2.prototype.__proto__);//返回Object对象
console.log(s2.__proto__.__proto__.__proto__);//返回null
console.log(S2.prototype.__proto__.__proto__);//返回null
其实,S2的原型对象上还有原型对象,因为S2的原型对象也相当于只是Object对象的一个实例。
在这里我给大家画了一张图,便于大家理解原型链。
码子不易,小编如有说得不对的地方,望大家指点包含,谢谢
前端JavaScript面试100问(上)
1、解释一下什么是闭包 ?
原型就是一个为对象实例定义了一些公共属性和公共方法的对象模板。
原型链对象之间的继承关系通过构造函数的prototype指向父类对象,直到指向Object对象为止形成的指向链条。
通俗讲:原型链是原型对象创建过程的历史记录。
注:在javascript中,所有的对象都拥有一个__proto__属性指向该对象的原型(prototype) 。
3、说一下 es6 中你熟悉的一些内容 ?for(var i=0;i<arr.length-1;i ){ for(var j=0;j<arr.length-i-1;j ){ if(arr[j]>arr[j 1]){ var temp=arr[j]; arr[j]=arr[j 1]; arr[j 1]=temp; } } if(arr[j]===arr[j-1]) i ; }
for(var i=0;i<arr.length;i ){ var min=i; for(var j=i 1;j<arr.length;j ){ if(arr[j]<arr[min]) min=j; } if(min!==i){ var temp=arr[i]; arr[i]=arr[min]; arr[min]=temp; } if(arr[i]===arr[i 1])i ;}
function quicksort(arr) { if (arr.length <= 1) return arr; var centerIndex = ~~(arr.length / 2); var left = []; var right = []; for (var i = 0; i < arr.length; i ) { if (i === centerIndex) continue; if (arr[i] < arr[centerIndex]) left.push(arr[i]); else right.push(arr[i]); } return quickSort(left).concat(arr[centerIndex], quickSort(right)); }5、什么是事件轮询(EventLoop) ?
一个用来等待和发送消息和事件的程序结构。
shift()
unshift()
pop()
push()
reverse()
sort()
splice()
concat()
every()
filter()
forEach()
indexOf()
join()
lastIndexOf()
map()
some()
every()
slice()
reduce()
reduceRight()
flat()
flatMap()
find()
7、for 循环与 forEach 的区别 ?function cloneObject(source, target) { if (target === undefined) { if (Node.prototype.isPrototypeOf(source)) { target = document.createElement(source.nodeName); target.style = source.style.cssText; } else if (source.constructor === Uint8Array) { target = new source.constructor(Array.from(source)); } else if (source.constructor === Date || source.constructor === RegExp || source.constructor === Set || source .constructor === Map) { target = new source.constructor(source); } else if (source.constructor === Function) { var arg = source.toString().match(/\((.*?)\)/)[1]; var content = source.toString().replace(/\n|\r/g, "").match(/\{(.*)\}/)[1]; target = new Function(arg, content) } else { target = new source.constructor(); } } var names = Object.getOwnPropertyNames(source).concat(Object.getOwnPropertySymbols(source)); for (var i = 0; i < names.length; i ) { if (names[i] === "constructor") { Object.defineProperty(target, "constructor", { value: source.constructor }); continue; } var desc = Object.getOwnPropertyDescriptor(source, names[i]); if ((typeof desc.value === "object" && desc.value !== null) || typeof desc.value === "function") { var o = cloneObject(desc.value) Object.defineProperty(target, names[i], { value: o, enumerable: desc.enumerable, writable: desc.writable, configurable: desc.configurable }) } else { Object.defineProperty(target, names[i], desc); } } return target; }
1、Object.assign(目标对象,源对象) 2、var obj1={} for(var key in obj){ obj1[key]=obj[key]} 3、obj1={...obj};9、url 的组成 ?
http:/https: 协议
www.baidu.com 域名
:8080 端口
/sf/vsearch 路径
?wd=百度热搜 查询(可有可无)
#a=1&b=2 哈希值(可有可无)
10、常见的跨域方式 ?存储方式 作用与特性 存储数量及大小
存储方式
存储用户信息,获取数据需要与服务器建立连接。
以路径存储,上层路径不能访问下层的路径cookie,下层的路径cookie可以访问上层的路径cookie
作用与特性
可存储的数据有限,且依赖于服务器,无需请求服务器的数据尽量不要存放在cookie 中,以免影响页面性能。
可设置过期时间。
存储数量及大小 将cookie控制在4095B以内,超出的数据会被忽略。
IE6或更低版本 最多存20个cookie;
IE7及以上
版本 多可以有50个;
Firefox多 50个;
chrome和Safari没有做硬性限制。
cookie最大特征就是可以在页面与服务器间互相传递,当发送或者接受数据时自动传递
localStorage
存储客户端信息,无需请求服务器。
数据永久保存,除非用户手动清理客户端缓存。
开发者可自行封装一个方法,设置失效时间。5M左右,各浏览器的存储空间有差异。
任何地方都可以存都可以取
操作简单
sessionStorage
存储客户端信息,无需请求服务器。
数据保存在当前会话,刷新页面数据不会被清除,结束会话(关闭浏览器、关闭页面、跳转页面)数据失效。
5M左右,各浏览器的存储空间有差异。
同页面不同窗口中数据不会共享
15、输入 url 到打开页面 都做了什么事情 ?创建xhrvar xhr=new XMLHTTPRequest()侦听通信状态改变的事件xhr.addEventListener("readystatechange",readyStateChangeHandler);Method 分为 get post put delete等等Async 异步同步name和password是用户名和密码xhr.open(Method,URL,Async,name,password)发送内容给服务器xhr.send(内容) function readyStateChangeHandler(e){ 当状态是4时,并且响应头成功200时, if(xhr.readyState===4 && xhr.status===200){ 打印返回的消息 console.log(xhr.response) }}17、如何实现继承 ?
function A(x,y){this.x = xthis.y = y}A.prototype.run = function(){}// 寄生继承 二者一起使用function B(x,y){A.call(this,x,y) // 借用继承}B.prototype = new A() // 原型继承// 组合继承Function.prototype.extends = function(superClass){ function F(){}F.prototype = superClass.prototype if(superClass.prototype.constructor !== superClass){ Object.defineProperty(superClass.prototype,'constructor',{value:superClass})}let proto = this.prototypethis.prototype = new F()let names = Reflect.ownKeys(proto) for(let i = 0; i < names.length;i ){ let desc = Object.getOwnPropertyDescriptor(proto,names[i]) Object.defineProperty(this.prototypr,name[i],desc)}this.prototype.super = function(arg){ superClass.apply(this,arg)}this.prototype.supers = superClass.prototype}
节流是指当一个事件触发的时候,为防止事件的连续频繁触发,设置定时器,达到一种一段事件内只触发一次的效果,在当前事件内不会再次触发,当前事件结束以后,再次触发才有效.
function thro(cb,wait){let timeOutreturn function(){ if(timeOut) return timeOut = setTimeout(function(){ cb() clearTimeout(timeOut) timeOut = null },wait)}}
防抖是指当一个事件触发的时候, 为防止频繁触发事件, 设置定时器,以达到一种 频繁触发期间不处理, 只有当最后一次连续触发结束以后才处理
function debounce(cb,wait){let timerreturn function(){ clearTimeout(timer) timer = setTimeout(()=>cb(),wait)}}20、什么是 Promise ?
Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;
从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。
promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行
promise是用来解决两个问题的:
回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象
promise可以支持多个并发的请求,获取并发请求中的数据
这个promise可以解决异步的问题,本身不能说promise是异步的
21、普通函数与箭头函数的区别 ?普通函数和箭头函数的区别:
共23种设计模式,介绍其中6种应用较为广泛的模式。
区别:
垃圾回收是动态存储管理技术,会自动地释放“垃圾‘’(不再被程序引用的对象),按照特定的垃圾收集算法来实现资源自动回收的功能。回收的两种机制
for(var i=0;i<arr.length;i ){for(var j=i 1;j<arr.length;){if(arr[i]===arr[j]) arr.splice(j,1);else j ; // 核心}}
var arr1=[];xt: for(var i=0;i<arr.length;i ){for(var j=0;j<arr1.length;j ){if(arr1[j]===arr[i]) continue xt;}arr1.push(arr[i]);}
var arr1=[];for(var i=0;i<arr.length;i ){if(arr1.indexOf(arr[i])<0) arr1.push(arr[i])}
var arr1=[];for(var i=0;i<arr.length;i ){if(!(~arr1.indexOf(arr[i]))) arr1.push(arr[i])}
var arr1=[];for(var i=0;i<arr.length;i ){if(!arr1.includes(arr[i])) arr1.push(arr[i])}
arr=[1,2,3,1,2,3,1,2,3]new Set(arr);26、判断对象为空 ?
使用JSON.stringify()将对象转换为json字符串;
JSON.stringify(obj) === '{}'
使用for...in循环遍历对象除Symbol以外的所有可枚举属性,当对象有属性存在返回false, 否则返回true。const obj = {}function isObjectEmpty(obj){for(var key in obj){return false}return true}console.log(isObjectEmpty(obj))
Object.getOwnPropertyNames() 方法会返回该对象所有可枚举和不可枚举属性的属性名(不含Symbol
属性)组成的数组。然后再通过判断返回的数组长度是否为零,如果为零的话就是空对象。
Object.getOwnPropertyNames(obj).length === 0
Object.keys() 是 ES5 新增的一个对象方法,该方法返回一个数组,包含指定对象自有的可枚举属性(不
含继承的和Symbol属性)。用此方法只需要判断返回的数组长度是否为零,如果为零的话就是空对象。
27、如何用一次循环找到数组中两个最大的值 ?var arr=[1,4,10,11,11,2,5,7,2,3,4];var [max,second]=arr[0]>arr[1] ? [arr[0],arr[1]] : [arr[1],arr[0]]; for(var i=2;i<arr.length;i ){ if(arr[i]>max){ second=max; max=arr[i]; }else if(arr[i]<=max && arr[i]>second){ second=arr[i]; }}28、new 一个对象的过程 ?
因为箭头函数没有prototype也没有自己的this指向并且不可以使用arguments。
30、如何实现数组的复制 ?var arr1=[]; for(var i=0;i<arr.length;i ){ if(i in arr) arr1[i]=arr[i]}
var arr1=[...arr];
var arr1=arr.slice();
var arr1=arr.concat();
var arr1=arr.map(item=>item);
var arr1=arr.reduce((v,t)=>v.push(t),[])