本文是根据知乎 爱前端不爱恋爱提供的目录整理供大家学习,后将持续更新
1、原型/原型链/构造函数/实例/继承
2、有几种方式可以实现继承
3、用原型实现继承有什么缺点,怎么解决
4、arguments
5、数据类型判断
6、作用域链、闭包、作用域
7、Ajax的原生写法
8、对象深拷贝、浅拷贝
9、图片懒加载、预加载
10、实现页面加载进度条
一、原型/原型链/构造函数/实例/继承
原型prototype
,它是函数所独有的,它是从一个函数指向一个对象。它的含义是函数的原型对象,也就是这个函数(其实所有函数都可以作为构造函数)所创建的实例的原型对象。
原型链是指一个对象通过__proto__
访问一个属性发现没有就去父对象,找一直到终点还没有返回null
这形成的一条链是原型链。
构造函数function Foo () {}; var f1 = new Foo()
这个Foo()
就是构造函数
这个f1
就是实例
继承可以使得子类具有父类的属性和方法或者重新定义、追加属性和方法等。
JS原型、原型链、构造函数、实例与继承
帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)
二、有几种方式可以实现继承
其实理解继承,主要是理解构造函数,实例属性和原型属性的关系。要想实现继承,将不同的对象或者函数联系起来,总共就以下几种思路:
原型链:父类的实例当做子类的原型。如此子类的原型包含父类定义的实例属性,享有父类原型定义的的属性。
借用构造函数:子类直接使用父类的构造函数。如此子类的实例直接包含父类定义的实例属性。
原型式:复制父类原型属性给子类原型。如此,子类实例享有父类定义的原型属性。
寄生式:思路与3一样,只是利用工厂模式对复制的父类原型对象进行增强。
然后,1,2思路结合,实例属性继承用借用构造函数保证独立性,方法继承用原型链保证复用性,就是组合模式。 4,2思路结合,或者说3,4与1,2思路结合,实例属性继承用借用构造函数保证独立性,方法继承用原型复制增强的方式,就是寄生组合模式。
ES5实现继承的六种方式
1. 原型链
2. 借用构造函数
3. 组合继承
4. 原型式继承
5. 寄生式继承
6. 寄生组合式继承
ES6实现继承
三、用原型实现继承有什么缺点,怎么解决
缺点:
- 来自原型对象的引用属性是所有实例共享的。
- 创建子类实例时,无法向父类构造函数传参。
解决:
- 寄生组合式继承是大家公认的最好的实现引用类型继承的方法。
- ES6新增class和extends语法,用来定义类和实现继承,底层也是采用了寄生组合式继承。
四、arguments
arguments
对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。此对象包含传递给函数的每个参数,第一个参数在索引0处。
例
function name(){
console.log(arguments[0],arguments[1])
}
name('hello','world');//hello world
五、数据类型判断
ECMAScript变量可能包含两种不同数据类型的值:基本类型值和引用类型值。基本类型值指的是简单的数据段,而引用类型值指那些可能由多个值构成的对象。
基本数据类型:Undefined
、 Null
、 Boolean
、 Number
和String
这5种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。
typeof
操作符是确定一个变量是字符申、数值、 布尔值, 还是undefined的最佳工具。 如果变量的值是一个对象或null,则typeof操作符会像下面例子中所示的那样返回 ” object ”
var s = "Nicholas ”
var b = true;
var i = 22;
var u;
var n = null;
var o = new Object();
alert(typeof s); //string
alert ( typeof i); //number
alert ( typeof b); //boolean
alert ( typeof u ); //undefined
alert(typeof n); //object
alert (typeof o); //object
虽然在检测基本数据类型时typeof
是非常得力的助手,但在检测引用类型的值时,这个操作符的 用处不大。通常,我们并不是想知道某个值是对象,而是想知道它是什么类型的对象。为此,ECMAScript 提供了instanceof
操作符, 其谱法如下所示:
result = variable instanceof constrυctor
根据规定.所有引用类型的值都是Object
的实例。因此,在检测一个引用类型值和Object
构造函数时,instanceof
操作符始终会返回true
。 当然 , 如果使用instanceof
操作符检测基本类型的 值, 则该操作符始终会返回false
, 因为基·本类型不是对象。
JS 中对变量类型的判断
六、作用域链、闭包、作用域
所有变量(包括基本类型和引用类型)都存在于一个执行环境(也称为作用域)当中, 这个执行环境决定了变量的生命周期, 以及哪一部分代码可以访问其中的变。以下是关于执行环境的几点总结:
- 执行环境有全局执行环境(也称为全局环境)和函数执行环境之分;
- 每次进入一个新执行环境. 都会创建一个用于搜索变量和函数的作用域链;
- 函数的局部环镜不仅有权访问函数作用域中的变量, 而且有权访问其包含(父)环境, 乃至全局环境;
- 全局环境只能访问在全局环境中定义的变量和函数, 而不能直接访问局部环境中的任何数据;
- 变量的执行环境有助于确定应该何时释放内存。
闭包是指有仅访问另一个 函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数内部创建另一个函数
深入理解JavaScript中的作用域、作用域链和闭包
七、Ajax的原生写法
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>JavaScript AJAX原生写法 面试题</title>
</head>
<body>
<script type="text/javascript">
var Ajax = {
get: function(url, fn) {
//创建XMLHttpRequest对象
var xhr = new XMLHttpRequest();
//true表示异步
xhr.open('GET', url, true);
xhr.onreadystatechange = function() {
// readyState == 4说明请求已完成
if(xhr.readyState == 4 && xhr.status == 200 || xhr.status == 304) {
//responseText:从服务器获得数据
fn.call(this, xhr.responseText);
}
};
xhr.send();
},
post: function(url, data, fn) { //datat应为'a=a1&b=b1'这种字符串格式
var xhr = new XMLHttpRequest();
xhr.open("POST", url, true);
// 添加http头,发送信息至服务器时内容编码类型
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
xhr.onreadystatechange = function() {
if(xhr.readyState == 4 && (xhr.status == 200 || xhr.status == 304)) {
fn.call(this, xhr.responseText);
}
};
xhr.send(data);
}
}
</script>
</body>
</html>
八、对象深拷贝、浅拷贝
浅拷贝:只拷贝对象的一层,深层次对象级别的就拷贝引用,对深层次对象改变会影响到原对象
深拷贝:拷贝多层,包括深层次对象,对深层次对象改变不会影响到原对象
终于弄清楚JS的深拷贝和浅拷贝了
javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法
Object对象的浅拷贝与深拷贝方法详解
九、图片懒加载、预加载
懒加载又称延迟加载,先延迟加载甚至是不加载图片,当符合特定条件时再加载
预加载是提前加载到本地,当需要查看图片是直接从本地取
图片懒加载和预加载
十、实现页面加载进度条
代码转自CSDN博主「&星期八&」的原创文章进入页面加载进度条
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>进度条</title>
<style>
*{
margin: 0;
padding: 0;
}
#progress{
width: 100%;
height: 30px;
background: #00bc12;
}
#bar{
width: 1%;
height: 30px;
margin-top: 1px;
background: #e4b4e4;
}
</style>
</head>
<body>
<div id="progress">
<div id="bar"></div>
</div>
<div><h3 id="text-progress">0%</h3></div>
</body>
<script>
function action(){
var iSpeed=1;
obj=setInterval(function(){
iSpeed+=1;
if(iSpeed>=100){ // 设置达到多少进度后停止
clearInterval(obj);
}
bar.style.width=iSpeed+'%';
document.getElementById('text-progress').innerHTML=iSpeed+'%';
},100);
}
action();
</script>
</html>