米娜桑,哦哈哟~

该篇章主要基于链接中的参考内容和代码测试得出的结论,面向具有一定基础的前端开发者。如有错误,请指出与包涵。


原型链的解释

白话翻译:原型链就相当于对象上的一个链条,通过隐性原型属性__proto__ 将其他相关的属性绑定以达到引用的效果,其链条的终点就是 Object.prototype,这就是原型链。

class.prototype === obj.__proto__

Object.create()声明的对象

Object.create({name: 1}) 相当于在这个对象的链条上再增加一条链条__proto__,所以 Object.create(null) 的结果是没有任何隐藏属性非常纯净且可高度定制的 {} (一般用于一些开源项目),当然通过

let a = {}
a.__proto__ = null

也可以获得纯净的对象,不过生成的性能一般,通过以下代码实现 Object.create()。

function create(obj) {
let F = function () {}
F.prototype = obj
return new F()
} function create(obj) {
let a = {}
a.__proto = obj
return a
}

Function.prototype.bind() 的特别之处

通过 Function.prototype.bind() 声明的函数不是 Function 的实例,故不存在class.prototype === obj.__proto__;不过可以通过

Object.prototype.toString.call()可以得知它依然是一个函数。

并与 Function.prototype 是一致的。


new

  1. new 的过程如下

创建有 Object 函数实例出来的空对象;

将该对象绑定到相应的构造函数上,其此为 this 的上下文,如果没有返回对象的话,就返回 this

function zxNew() {
let fn = arguments[0]
if (typeof fn !== 'function') {
throw new TypeError('first param must be a function')
}
Array.prototype.shift.call(arguments)
let obj = Object.create(null);
obj.__proto__ = fn.prototype;
let res = fn.apply(obj, arguments);
return res instanceof Object ? res : obj
}

原型链继承的方式

原型继承

function Parent () {
this.name = 'temax'
} Parent.prototype.fn = function () {
console.log(233)
} function Child () {} Child.prototype = new Parent() let child = new Child()

缺点:属性共享、不能传参

经典继承——使用 call 方法借用构造函数的方式

function Parent (name) {
this.name = name
} Parent.prototype.fn = function () {
console.log(233)
} function Child (name) {
Parent.call(this, name)
} let child = new Child('temax')

缺点:不能继承prototype上的属性

组合继承——即原型链继承和经典继承的结合

function Parent(name) {
this.name = name
} Parent.prototype.fn = function () {
console.log(233)
} function Child(name) {
Parent.call(this, name)
} Child.prototype = new Parent()
Child.prototype.constructor = Child let child = new Child(1)

缺点:父类函数执行两次

组合继承的优化

function Parent(name) {
this.name = name
} function.prototype.fn = function () {
console.log(233)
} function Child(name) {
Parent.call(this, name)
} Child.prototype = Parent.prototype
child.prototype.constructor = Child let child = new Child()

缺点:prototype 的保存地址其实就是父级的保存地址,也就是说如果改变 child.prototype 会直接影响到父级的 prototype,所以需要加一个__proto__进行隔离

寄生组合的方式——比较理想的组合方式

function Parent(name) {
this.name = name
} function.prototype.fn = function () {
console.log(233)
} function Child(name) {
Parent.call(this, name)
} Child.prototype = Object.create(Parent.prototype)
child.prototype.constructor = Child

class的继承方式

class Parent{

}
class Child extends Parent{ }

this的指向

  1. this永远指向最后调用的对象。

    也就是说 a.b.c.fn(),那么 fn 里面的 this 的指向 c 的属性。

    如果令 d = b.c.fn;则 a.d() 中的 this 是指向 a 的。
  2. setTimeout 的 function 中的 this 是指向 window 对象的。因为 setTimeout 实则为 window.setTimeout。
  3. 可通过定义this的变量来调用或使用 apply/call/bind 的方式改变 this 指向。

箭头函数的this

  1. 自身没有声明 this,所以会在作用域链上找最近的 this。
  2. 不可以当作构造函数。
  3. 不能用作 Generator 函数。
  4. 不能使用 arguments,arguments 可以用 ...rest 取代。

apply、call、bind

  1. 可以通过 apply 和 call 对对象进行调用, 使得函数内的 this 绑定到该调用的值。
  2. apply 和 call 的区别就是传入方式的不一样,前者是数组传参的方式,后者是直接传参的方式。
  3. bind 跟 call 一致,只不过 bind 会创建并返回一个新的函数。
  4. 实现机制如下

call (apply同理,只是改变参数的形式)

Function.prototype.call = function(){
if (typeof this !== 'function') {
throw new TypeError('Called object must be a function')
}
let obj = Object(arguments[0]) || window,
obj.fn = this,
result;
arr = arguments.slice();
arr.shift();
result = obj.fn(...arr)
delete obj.fn
return result
}

bind

如果要模仿 Function.prototype.bind() 得到的函数 fn,需要设置

fn.__proto__ = Object.prototype
fn.prototype = undifned
Function.prototype.bind1 = function () {
let fn = this;
if(typeof fn === 'function'){
if(fn !== Function.prototype){
let obj = Object(arguments[0]) || window,
args = Array.prototype.slice.call(arguments,1),
TempFn = function () {},
FnBind = function () {
//当使用new来构造函数(通过bind得到的)时,会忽略bind(obj)的obj
//对于这个的理解,应该结合new和call的实现来解释,这个时候的this是指向 Object.create(null),如果没有设置prototype的话
//因为原生得到的(new fn1) instanceof fn1 为 true,
// (new fn1) instanceof fn 也为 true,
//又因为 TempFn.prototype = fn.prototype;(只要满足 ojb.__proto__ === class.prototype.constructor)
//所以用改造后得到的 (new fn2) instanceof TempFn 为 true //简单来说就是,当为构造函数的时候,这里的this是等于指向实例,而实例 instanceof fn1 为true, 实例 instanceof fn也为true,
//而只要满足 ojb.__proto__ === class.prototype
//那么 instanceof 得到的就是 true,所以可以用 this instanceof TempFn 来表示
let bindArgs = Array.prototype.slice.call(arguments);
return fn.apply(this instanceof TempFn ? this : obj, args.concat(bindArgs))
};
TempFn.prototype = fn.prototype;
FnBind.prototype = new TempFn;
return FnBind
}else {
fn.prototype = undefined
fn.__proto__ = Object.prototype
return fn
}
}else {
throw TypeError('Called object must be a function')
}
}

事件循环

  1. 宏任务:整体代码;setTimeout;setInterval,宏任务消息队列

    微任务:Promise; process.nextTick,微任务消息队列
  2. 通过以下代码测试
setTimeout(function(){
console.log('定时器开始啦')
}); new Promise(function(resolve){
console.log('马上执行for循环啦');
for(var i = 0; i < 10000; i++){
i == 99 && resolve();
}
}).then(function(){
console.log('执行then函数啦')
}); console.log('代码执行结束');


节点操作

  1. 添加节点可以通过 appendChild
  2. 通过 innerText 对节点添加文本信息
  3. 也可以通过 innerHTML 对节点添加 html 文本
  4. 利用 document.createElement 添加对应元素。
  5. 通过 node.addEventListener(type,listener,capture) 添加事件。第三参数为是否捕获,默认false,即冒泡
  6. document 为最大的节点。
  7. 当然也可以通过 DocumentFragment 来减少 dom 操作
  8. 以下是 ul 元素添加 li 元素的例子
let ul = document.querySelector('.cul');
// let ul = document.querySelectorAll('.cul')[0];
let a = '';
function myFunction(e){console.log(e)}
for(let i=0;i<5;i++){
a += `<li onclick='myFunction(${i})'>${i}</li>`
}
ul.innerHTML = a
let ul = document.querySelectorAll('.cul')[0];
for(let i=0;i<5;i++){
let a = document.createElement('li');
a.innerHTML = i
a.addEventListener('click',function () {
console.log(i)
})
ul.appendChild(a)
}
let ul = document.querySelectorAll('.cul')[0];
let fragment = document.createDocumentFragment()
for(let i=0;i<5;i++){
let a = document.createElement('li');
a.innerHTML = i
a.addEventListener('click',function () {
console.log(i)
})
fragment.appendChild(a)
}
ul.appendChild(fragment)

【JavaScript】要点知识的个人总结(1)的更多相关文章

  1. Javascript基础知识总结一

    Javascript基础知识总结一 <!DOCTYPE html> <html> <head lang="en"> <meta chars ...

  2. javascript 要点

    javascript 要点 1 JavaScript:写入 HTML 输出 document.write("<h1>This is a heading</h1>&qu ...

  3. 学习javascript基础知识系列第二节 - this用法

    通过一段代码学习javascript基础知识系列 第二节 - this用法 this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象.但是在javascr ...

  4. 学习javascript基础知识系列第三节 - ()()用法

    总目录:通过一段代码学习javascript基础知识系列 注意: 为了便于执行和演示,建议使用chrome浏览器,按F12,然后按Esc(或手动选择)打开console,在console进行执行和演示 ...

  5. javascript常用知识点集

    javascript常用知识点集 目录结构 一.jquery源码中常见知识点 二.javascript中原型链常见的知识点 三.常用的方法集知识点 一.jquery源码中常见的知识点 1.string ...

  6. 七个开法者经常忽略或误用的JavaScript基本知识

    七个开法者经常忽略或误用的JavaScript基本知识 翻译自 http://tech.pro/tutorial/1453/7-javascript-basics-many-developers-ar ...

  7. JavaScript 基础知识 - BOM篇

    前言 本篇文章是JavaScript基础知识的BOM篇,如果前面的<JavaScript基础知识-DOM篇>看完了,现在就可以学习BOM了. 注意: 所有的案例都在这里链接: 提取密码密码 ...

  8. JavaScript数组知识

    JavaScript数组知识 <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  9. JS控制语句 编程练习 学生数据,分别是姓名、性别、年龄和年级,接下来呢,我们要利用JavaScript的知识挑出其中所有是大一的女生的的名字哦。

    编程练习 在一个大学的编程选修课班里,我们得到了一组参加该班级的学生数据,分别是姓名.性别.年龄和年级,接下来呢,我们要利用JavaScript的知识挑出其中所有是大一的女生的的名字哦. 学生信息如下 ...

  10. AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解

    AST抽象语法树——最基础的javascript重点知识,99%的人根本不了解 javascriptvue-clicommonjswebpackast  阅读约 27 分钟 抽象语法树(AST),是一 ...

随机推荐

  1. 前端每日实战:147# 视频演示如何用纯 CSS 创作透视按钮的悬停特效

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/qJEdKb 可交互视频 此视频是可 ...

  2. 通读Python官方文档之cgitb

    cgitb CGI脚本异常管理 源代码:Lib/cgitb.py cgitb模块为Python脚本提供了一个特殊的异常管理器.名字有点误导人,它最初设计是为了以HTML格式展示cgi脚本的大量异常信息 ...

  3. 前端每日实战:61# 视频演示如何用纯 CSS 创作一只咖啡壶

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/ZRjGGy 可交互视频 此视频是可 ...

  4. 集成google翻译的小tips

    文章首发于github.io 2018-08-04 12:43:20 google翻译的强大,就像我们公司的slogan : "让语言无国界,让世人心相通" 友情提示: googl ...

  5. idea新建springboot项目

    不多说废话,直接进入正题,按照下面的步骤创建一个springboot项目一般不会出错,当然不排除可能会有一些脸黑的,不过应该问题不大. 第一步,如果你是在已有的项目里面,新建一个springboot项 ...

  6. 鸟哥的Linux私房菜基础学习篇(第三版)——阅读笔记(二)

    第一章 Linux是什么 1.Linux是什么 一套操作系统 早期的Linux是针对386开发的 具有可移植性 2.Unix及Linux的发展史 1973年,Unix诞生,Ritchie等人以C语言写 ...

  7. 基于Redis未授权访问的挖矿蠕虫分析

    0x01 攻击方式 利用的是通用漏洞入侵服务器并获得相关权限,从而植入挖矿程序再进行隐藏. 通过对脚本的分析,发现黑客主要是利用 Redis未授权访问漏洞进行入侵.脚本里有个python函数. imp ...

  8. IPFS(星际文件系统)-初步接触

    〇.IPFS介绍 从HTTP到IPFS,星际文件系统能变革信息传播的方式吗? 戴嘉乐:详解IPFS的本质.技术架构以及应用 以下为实现相关摘要 1.存储 在IPFS中,信息可以存储进IPFS系统中的块 ...

  9. Python习题集(四)

    每天一习题,提升Python不是问题!!有更简洁的写法请评论告知我! https://www.cnblogs.com/poloyy/category/1676599.html 题目 如果一个 3 位数 ...

  10. C/C++、C#、JAVA(二):基本类型和转换操作

    基本类型和转换操作 数据类型 C语言中的基本类型如下. 类型 存储大小 值范围 char 1 字节 -128 到 127 或 0 到 255 unsigned char 1 字节 0 到 255 si ...