JavaScript的高级学习笔记
基本(值)类型
数据类型 | 可表示的值 | 可判断方式 |
---|---|---|
Number | 任意数值 | typeof |
String | 任意字符串 | typeof |
Boolean | true/false | typeof |
Undefined | undefined | typeof/=== |
Null | null | === |
===
判断 Undefined
和 Null
,因为这两种数据类型都只有一个值。typeof
判断 Null
结果为 object
。对象(引用)类型
数据类型 | 可判断方式 |
---|---|
Object | typeof/instanceof |
Array | instanceof |
Function | typeof |
类型判断
相关问题
undefined与null的区别?
什么时候给变量赋值为null呢?
//a将指向一个对象, 但对象此时还没有确定
var a = null
//让a指向的对象成为垃圾对象
a = null
1 2 3 4
复制
严格区别变量类型与数据类型?
什么是数据?
什么是变量?
什么是内存?
内存,数据,变量三者之间的关系
关于引用变量赋值问题
在js调用函数时传递变量参数时, 是值传递还是引用传递?
JS引擎如何管理内存?
什么是对象?
为什么要用对象?
对象的组成
如何访问对象内部数据?
什么时候必须使用['属性名']的方式?
特别的对象
什么是函数?
为什么要用函数?
如何定义函数?
如何调用(执行)函数?
回调函数的理解
函数也是对象
函数的3种不同角色
函数中的this
匿名函数自调用(IIFE)
(function(w, obj){
//实现代码
})(window, obj)
1 2 3
复制
函数的prototype属性
给原型对象添加属性(一般都是方法)
显式原型与隐式原型
原型链
原型链属性问题
instanceof是如何判断的?
Function是通过new自己产生的实例
原型链图解:
面试题
/*
测试题1
*/
var A = function() {
}
A.prototype.n = 1
var b = new A()
A.prototype = {
n: 2,
m: 3
}
var c = new A()
console.log(b.n, b.m, c.n, c.m) //1 undefine 2 3
/*
测试题2
*/
var F = function(){};
Object.prototype.a = function(){
console.log('a()')
};
Function.prototype.b = function(){
console.log('b()')
};
var f = new F();
f.a() //a()
f.b() //报错,下面不再执行
F.a() //a()
F.b() //b()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34
复制
变量提升与函数提升
执行上下文创建和初始化的过程 1.全局执行上下文(window)
2.函数执行上下文(对程序员来说是透明的)
执行上下文栈
理解
生命周期
面试题
/*
测试题1: 先执行变量提升, 再执行函数提升
*/
function a() {}
var a
console.log(typeof a) // 'function'
/*
测试题2:
*/
if (!(b in window)) {
var b = 1
}
console.log(b) // undefined
/*
测试题3:
*/
var c = 1
function c(c) {
console.log(c)
var c = 3
}
c(2) // 报错
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
复制
作用域
作用域与执行上下文关系
作用域链
面试题
var x = 10;
function fn() {
console.log(x);
}
function show(f) {
var x = 20;
f();
}
show(fn); //10
1 2 3 4 5 6 7 8 9
复制
var fn = function () {
console.log(fn)
}
fn() //输出fn函数
var obj = {
fn2: function () {
console.log(fn2)
//console.log(this.fn2)
}
}
obj.fn2() //报错
1 2 3 4 5 6 7 8 9 10 11 12
复制
如何产生闭包?
闭包到底是什么?
产生闭包的条件?
闭包的作用:
写一个闭包程序
// 1. 将函数作为另一个函数的返回值
function fn1() {
var a = 2
function fn2() {
a++
console.log(a)
}
return fn2
}
var f = fn1()
f() // 3
f() // 4
// 2. 将函数作为实参传递给另一个函数调用
function showDelay(msg, time) {
setTimeout(function () {
alert(msg)
}, time)
}
showDelay('atguigu', 2000)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
复制
问题
闭包的生命周期
闭包的应用:
缺点:
面试题
//代码片段一
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()()); //The Window
//代码片段二
var name2 = "The Window";
var object2 = {
name2 : "My Object",
getNameFunc : function(){
var that = this;
return function(){
return that.name2;
};
}
};
alert(object2.getNameFunc()()); //My Object
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
复制
function fun(n,o) {
console.log(o)
return {
fun:function(m){
return fun(m,n)
}
}
}
var a = fun(0)
a.fun(1)
a.fun(2)
a.fun(3)//undefined,0,0,0
var b = fun(0).fun(1).fun(2).fun(3)//undefined,0,1,2
var c = fun(0).fun(1)
c.fun(2)
c.fun(3)//undefined,0,1,1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
复制
内存溢出
内存泄露
Object构造函数模式
var obj = {};
obj.name = 'Tom'
obj.setName = function(name){
this.name = name
}
1 2 3 4 5
复制
对象字面量模式
var obj = {
name : 'Tom',
setName : function(name){
this.name = name
}
}
1 2 3 4 5 6
复制
工厂模式
function createPerson(name, age) { //返回一个对象的函数===>工厂函数
var obj = {
name: name,
age: age,
setName: function (name) {
this.name = name
}
}
return obj
}
1 2 3 4 5 6 7 8 9 10
复制
构造函数模式
function Person(name, age) {
this.name = name;
this.age = age;
this.setName = function(name){
this.name=name;
};
}
new Person('tom', 12);
1 2 3 4 5 6 7 8
复制
构造函数+原型的组合模式
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.setName = function(name){
this.name=name;
};
new Person('tom', 12);
1 2 3 4 5 6 7 8
复制
原型链继承 : 得到方法
// 定义父类型构造函数
function Parent(){}
// 给父类型的原型添加方法
Parent.prototype.test = function(){};
// 定义子类型的构造函数
function Child(){}
// 子类型的原型指向父类型实例
Child.prototype = new Parent();
// 将子类型原型的构造属性设置为子类型
Child.prototype.constructor = Child
// 给子类型原型添加方法
Child.prototype.test2 = function(){};
// 创建子类型的对象: 可以调用父类型的方法
var child = new Child();
// 有父类型的test()
child.test()
child.test2()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
复制
借用构造函数(假继承) : 得到属性
// 定义父类型构造函数
function Parent(xxx){
this.xxx = xxx
}
// 给父类型的原型添加方法
Parent.prototype.test = function(){};
// 定义子类型构造函数
function Child(xxx,yyy){
// 在子类型构造函数中调用父类型构造
Parent.call(this, xxx);//借用构造函数 this.Parent(xxx)
this.yyy = yyy;
}
//child.xxx为'a', 但child没有test()
var child = new Child('a', 'b');
1 2 3 4 5 6 7 8 9 10 11 12 13 14
复制
组合继承
// 定义父类型构造函数
function Parent(xxx){
this.xxx = xxx
}
// 给父类型的原型添加方法
Parent.prototype.test = function(){};
// 定义子类型构造函数
function Child(xxx,yyy){
// 在子类型构造函数中调用父类型构造(得到父类型的属性)
Parent.call(this, xxx);//借用构造函数 this.Parent(xxx)
this.yyy = yyy;
}
// 子类型的原型指向父类型实例(得到父类型的方法)
Child.prototype = new Parent();
// 将子类型原型的构造属性设置为子类型
Child.prototype.constructor = Child
// child.xxx为'a', 也有test()
var child = new Child();
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
复制
new一个对象背后做了些什么?
进程:
线程:
进程与线程的关系
线程池(thread pool)
比较单线程与多线程
浏览器运行是单进程还是多进程?
如何查看浏览器是否是多进程运行的呢?
浏览器运行是单线程还是多线程?
什么是浏览器内核?
不同的浏览器可能不太一样
内核由很多模块组成
如何证明js执行是单线程的?
为什么js要用单线程模式, 而不用多线程模式?
代码的分类:
js引擎执行代码的基本流程
定时器真是定时执行的吗?
定时器回调函数是在分线程执行的吗?
定时器是如何实现的?
代码分类
js引擎执行代码的基本流程:
模型的2个重要组成部分:
模型的运转流程
主线程
// 创建一个Worker对象并向它传递将在新线程中执行的脚本的URL
var worker = new Worker('worker.js');
// 绑定用来接收分线程返回的数据的回调
worker.onmessage = function(event){
// 接收到的分线程返回的数据
event.data
}
// 向分线程发送数据
worker.postMessage(number)
1 2 3 4 5 6 7 8 9
复制
分线程
function fibonacci(n) {
return n<=2 ? 1 : fibonacci(n-1) + fibonacci(n-2) //递归调用
}
// 绑定用来接收主线程发送过来的数据的回调
this.onmessage = function (event) {
// 接收到的主线程发送的数据
var number = event.data
var result = fibonacci(number)
// 向主线程返回数据
postMessage(result)
// alert(result) alert是window的方法, 在分线程不能调用
// 分线程中的全局对象不再是window, 所以在分线程中不可能更新界面
}
1 2 3 4 5 6 7 8 9 10 11 12 13
复制
相关API
不足