JavaScript
데이터 객체 중복 제거
resultData = [ { 'towerName':'AA', 'address':'asss' }, { 'towerName':'AA', 'address':'awsdwasd' }, { 'towerName':'BB', 'address':'awsdwasd' }, ] let hash = {}; resultData = resultData.reduce(function(item, next) { hash[next.towerName] ? '' : hash[next.towerName] = true && item.push(next); return item }, []) console.log(resultData)
크로스 도메인의 다양한 방법
먼저 브라우저의 동일 출처 정책을 이해하세요
동일 출처 정책/SOP 정책) 도입된 대회 브라우저의 핵심이자 가장 기본적인 보안 기능입니다. 동일 출처 정책이 없으면 브라우저는 XSS, CSRF 및 기타 공격에 취약해집니다. 소위 동일 출처란 "프로토콜 + 도메인 이름 + 포트"가 동일한 것을 의미합니다. 두 개의 서로 다른 도메인 이름이 동일한 IP 주소를 가리키더라도 동일한 출처에서 온 것이 아닙니다.
1 jsonp를 통한 도메인 간 1.) 기본 구현:
<script> var script = document.createElement('script'); script.type = 'text/javascript'; // 传参并指定回调执行函数为onBack script.src = 'http://www.....:8080/login?user=admin&callback=onBack'; document.head.appendChild(script); // 回调执行函数 function onBack(res) { alert(JSON.stringify(res)); } </script>
2, document.domain + iframe 크로스 도메인, 이 솔루션은 동일한 기본 도메인과 도메인 간 애플리케이션 시나리오로 제한됩니다. 다른 하위 도메인.
<iframe id="iframe" src="http://child.domain.com/b.html"></iframe> <script> document.domain = 'domain.com'; var user = 'admin'; </script>rrree
단점: 아래의 렌더링 및 로딩 최적화를 참조하세요
2.) 하위 창: (http://child.domain.com/b.html)
1.) 상위 창 : (http://www.domain.com/a.html)
3.nginx 프록시 교차 도메인
4. nodejs 미들웨어 프록시 교차 도메인
5입니다. 헤더 정보 보안 도메인 이름 설정
더 많은 도메인 간 콘텐츠를 보려면 https://segmentfault.com/a/11...
이벤트의 다양한 단계
를 참조하세요.1: 캡처 단계--> 2: 대상 단계 ---> 3: 버블링 단계
document ---> 대상 대상---> document
addEventListener의 세 번째 매개변수 설정 true와 false의 차이는 매우 분명합니다.
true는 요소가 이벤트의 "캡처 단계"에서 이벤트에 응답한다는 의미입니다(외부에서 내부로 전달되는 경우).
<script>
document.domain = 'domain.com';
// 获取父窗口中变量
alert('get js data from parent ---> ' + window.parent.user);
</script>
HTML을 구문 분석하여 DOM(DOM 트리) 구축, css/image/js 병렬 요청
CSS 파일 다운로드가 완료되고 CSSOM(CSS 트리) 구축 시작
CSSOM 구축이 완료되면, DOM Tree(렌더링 트리)
와 함께 Render가 생성됩니다. Layout(레이아웃): 화면에서 각 노드의 위치를 계산합니다.
Display(Painting): 그래픽 카드를 통해 화면에 페이지를 그립니다
DOM 트리와 렌더링 트리의 차이점:
DOM 트리는 헤드 및 숨겨진 요소를 포함하여 HTML 태그에 일대일로 대응합니다.
렌더링 트리에는 헤드 및 숨겨진 요소가 각각 포함되지 않습니다. 큰 텍스트 줄은 독립적인 노드입니다. 노드에는 해당 CSS 속성이 있습니다
다시 그리기와 리플로우(재배열)의 차이점과 관계는 무엇인가요?
Redraw: 렌더링 트리에 있는 요소의 모양(예: 색상)이 변경되고 레이아웃에 영향을 주지 않으면 다시 그리기가 발생합니다.
Reflow: 렌더링 트리에 있는 요소의 레이아웃(예: 크기, 크기 등) 위치, 숨기기/상태)가 변경되면 다시 그리기 리플로우가 발생합니다
참고: JS가 레이아웃 속성 값(예: offsetLeft, scrollTop, getCompulatedStyle 등)을 가져오면 리플로우. 브라우저는 리플로우를 통해 최신 값을 계산해야 하기 때문에
리플로우로 인해 반드시 다시 그리기가 발생하지만 다시 그리면 반드시 리플로우가 발생하지는 않습니다
리페인트와 리플로우를 최소화하는 방법은 무엇인가요?
요소에 대해 복잡한 작업을 수행해야 하는 경우 먼저 요소를 숨기고(표시: "없음") 작업이 완료된 후 표시할 수 있습니다.
여러 DOM 노드를 생성해야 하는 경우 다음을 사용하세요. DocumentFragment를 사용하여 한 번에 생성 document
를 추가하여 다음과 같이 레이아웃 속성 값을 캐시합니다. var left = elem.offsetLeft; 이러한 방식으로 left를 여러 번 사용하면 리플로우가 하나만 생성됩니다
피하십시오. 테이블 레이아웃 사용(테이블 요소가 리플로우를 트리거하면 테이블의 다른 모든 요소가 리플로우됩니다.)
CSS 표현식(표현식)을 사용하지 마세요. 값이 호출될 때마다(페이지 로드 포함) 다시 계산되기 때문입니다. )
css 속성 약어를 사용해 보세요. 예: border-width, border-style, border-color 대신 border 사용
요소 스타일 일괄 수정: elem.className 및 elem.style.cssText 대신 elem.style.xxx
스크립트 위치가 첫 화면 표시 시간에 영향을 주나요?
HTML을 구문 분석하여 DOM을 생성하는 과정에서 js 파일 다운로드는 병렬로 이루어지며 스크립트 노드에 대한 DOM 처리가 필요하지 않습니다. 따라서 스크립트의 위치는 첫 번째 화면 표시의 시작 시간에 영향을 미치지 않습니다.
브라우저에서 HTML을 구문 분석하는 것은 하향식 선형 프로세스이므로 HTML의 일부인 스크립트도 이 원칙을 따릅니다.
따라서 스크립트는 DomContentLoad를 지연하고 첫 번째 화면 콘텐츠의 위쪽 부분만 표시하므로 첫 번째 화면 콘텐츠에 영향을 미칩니다. 화면 표시된 완료 시간
JavaScript에서 범위 및 변수 선언 호이스팅을 설명하시겠습니까?
JavaScript 범위:
Java 및 C와 같은 언어에서 범위는 for 문, if 문 또는 {} 내의 영역으로, 이를 범위라고 합니다.
그리고 JavaScript에서 범위는 function(){} 내의 영역이며, 이를 함수 범위라고 합니다.프로토타입:
原型特点:
JavaScript对象是通过引用来传递的,当修改原型时,与之相关的对象也会继承这一改变
JavaScript有几种类型的值?,你能画一下他们的内存图吗
原始数据类型(Undefined,Null,Boolean,Number、String)-- 栈
引用数据类型(对象、数组和函数)-- 堆
两种类型的区别是:存储位置不同:
原始数据类型是直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据;
引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定,如果存储在栈中,将会影响程序运行的性能;
引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。
当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。
JavaScript如何实现一个类,怎么实例化这个类?
构造函数法(this + prototype) -- 用 new 关键字 生成实例对象
缺点:用到了 this 和 prototype,编写复杂,可读性差
function Mobile(name, price){ this.name = name; this.price = price; } Mobile.prototype.sell = function(){ alert(this.name + ",售价 $" + this.price); } var iPhone7 = new Mobile("iPhone7", 1000); iPhone7.sell();
Object.create 法 -- 用 Object.create() 生成实例对象
缺点:不能实现私有属性和私有方法,实例对象之间也不能共享数据
var Person = { firstname: "Mark", lastname: "Yun", age: 25, introduce: function(){ alert('I am ' + Person.firstname + ' ' + Person.lastname); } }; var person = Object.create(Person); person.introduce(); // Object.create 要求 IE9+,低版本浏览器可以自行部署: if (!Object.create) { Object.create = function (o) { function F() {} F.prototype = o; return new F(); }; }
极简主义法(消除 this 和 prototype) -- 调用 createNew() 得到实例对象
优点:容易理解,结构清晰优雅,符合传统的"面向对象编程"的构造
var Cat = { age: 3, // 共享数据 -- 定义在类对象内,createNew() 外 createNew: function () { var cat = {}; // var cat = Animal.createNew(); // 继承 Animal 类 cat.name = "小咪"; var sound = "喵喵喵"; // 私有属性--定义在 createNew() 内,输出对象外 cat.makeSound = function () { alert(sound); // 暴露私有属性 }; cat.changeAge = function(num){ Cat.age = num; // 修改共享数据 }; return cat; // 输出对象 } }; var cat = Cat.createNew(); cat.makeSound();
ES6 语法糖 class -- 用 new 关键字 生成实例对象
class Point { constructor(x, y) { this.x = x; this.y = y; } toString() { return '(' + this.x + ', ' + this.y + ')'; } } var point = new Point(2, 3);
Javascript如何实现继承?
构造函数绑定:使用 call 或 apply 方法,将父对象的构造函数绑定在子对象上
function Cat(name,color){ Animal.apply(this, arguments); this.name = name; this.color = color; }
实例继承:将子对象的 prototype 指向父对象的一个实例
Cat.prototype = new Animal(); Cat.prototype.constructor = Cat;
拷贝继承:如果把父对象的所有属性和方法,拷贝进子对象
function extend(Child, Parent) { var p = Parent.prototype; var c = Child.prototype; for (var i in p) { c[i] = p[i]; } c.uber = p; }
原型继承:将子对象的 prototype 指向父对象的 prototype
function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype; }
ES6 语法糖 extends:class ColorPoint extends Point {}
class ColorPoint extends Point { constructor(x, y, color) { super(x, y); // 调用父类的constructor(x, y) this.color = color; } toString() { return this.color + ' ' + super.toString(); // 调用父类的toString() } }
Javascript作用链域?
全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节
如果当前作用域没有找到属性或方法,会向上层作用域查找,直至全局函数,这种形式就是作用域链
谈谈this对象的理解
this 总是指向函数的直接调用者
如果有 new 关键字,this 指向 new 出来的实例对象
在事件中,this指向触发这个事件的对象
IE下 attachEvent 中的this总是指向全局对象Window
eval是做什么的?
eval的功能是把对应的字符串解析成JS代码并运行
应该避免使用eval,不安全,非常耗性能(先解析成js语句,再执行)
由JSON字符串转换为JSON对象的时候可以用 eval('('+ str +')');
什么是 Window 对象? 什么是 Document 对象?
Window 对象表示当前浏览器的窗口,是JavaScript的顶级对象。
我们创建的所有对象、函数、变量都是 Window 对象的成员。
Window 对象的方法和属性是在全局范围内有效的。
Document 对象是 HTML 文档的根节点与所有其他节点(元素节点,文本节点,属性节点, 注释节点)
Document 对象使我们可以通过脚本对 HTML 页面中的所有元素进行访问
Document 对象是 Window 对象的一部分,可通过 window.document 属性对其进行访问
介绍 DOM 的发展
DOM:文档对象模型(Document Object Model),定义了访问HTML和XML文档的标准,与编程语言及平台无关
DOM0:提供了查询和操作Web文档的内容API。未形成标准,实现混乱。如:document.forms['login']
DOM1:W3C提出标准化的DOM,简化了对文档中任意部分的访问和操作。如:JavaScript中的Document对象
DOM2:原来DOM基础上扩充了鼠标事件等细分模块,增加了对CSS的支持。如:getComputedStyle(elem, pseudo)
DOM3:增加了XPath模块和加载与保存(Load and Save)模块。如:XPathEvaluator
介绍DOM0,DOM2,DOM3事件处理方式区别
DOM0级事件处理方式:
btn.onclick = func;
btn.onclick = null;
DOM2级事件处理方式:
btn.addEventListener('click', func, false);
btn.removeEventListener('click', func, false);
btn.attachEvent("onclick", func);
btn.detachEvent("onclick", func);
DOM3级事件处理方式:
eventUtil.addListener(input, "textInput", func);
eventUtil
是自定义对象,textInput
是DOM3级事件
事件的三个阶段
捕获、目标、冒泡
介绍事件“捕获”和“冒泡”执行顺序和事件的执行次数?
按照W3C标准的事件:首是进入捕获阶段,直到达到目标元素,再进入冒泡阶段
事件执行次数(DOM2-addEventListener):元素上绑定事件的个数
注意1:前提是事件被确实触发
注意2:事件绑定几次就算几个事件,即使类型和功能完全一样也不会“覆盖”
事件执行顺序:判断的关键是否目标元素
非目标元素:根据W3C的标准执行:捕获->目标元素->冒泡(不依据事件绑定顺序)
目标元素:依据事件绑定顺序:先绑定的事件先执行(不依据捕获冒泡标准)
最终顺序:父元素捕获->目标元素事件1->目标元素事件2->子元素捕获->子元素冒泡->父元素冒泡
注意:子元素事件执行前提 事件确实“落”到子元素布局区域上,而不是简单的具有嵌套关系
在一个DOM上同时绑定两个点击事件:一个用捕获,一个用冒泡。事件会执行几次,先执行冒泡还是捕获?
该DOM上的事件如果被触发,会执行两次(执行次数等于绑定次数)
如果该DOM是目标元素,则按事件绑定顺序执行,不区分冒泡/捕获
如果该DOM是处于事件流中的非目标元素,则先执行捕获,后执行冒泡
事件的代理/委托
事件委托是指将事件绑定目标元素的到父元素上,利用冒泡机制触发该事件
可以减少事件注册,节省大量内存占用
可以将事件应用于动态添加的子元素上
优点:
缺点:
使用不当会造成事件在不应该触发时触发
示例:
ulEl.addEventListener('click', function(e){ var target = event.target || event.srcElement; if(!!target && target.nodeName.toUpperCase() === "LI"){ console.log(target.innerHTML); } }, false);
IE与火狐的事件机制有什么区别? 如何阻止冒泡?
IE只事件冒泡,不支持事件捕获;火狐同时支持件冒泡和事件捕获
IE的事件处理和W3C的事件处理有哪些区别?
绑定事件
W3C: targetEl.addEventListener('click', handler, false);
IE: targetEl.attachEvent('onclick', handler);
删除事件
W3C: targetEl.removeEventListener('click', handler, false);
IE: targetEl.detachEvent(event, handler);
事件对象
W3C: var e = arguments.callee.caller.arguments[0]
IE: window.event
事件目标
W3C: e.target
IE: window.event.srcElement
阻止事件默认行为
W3C: e.preventDefault()
IE: window.event.returnValue = false
阻止事件传播
W3C: e.stopPropagation()
IE: window.event.cancelBubble = true
W3C事件的 target 与 currentTarget 的区别?
target 只会出现在事件流的目标阶段
currentTarget 可能出现在事件流的任何阶段
当事件流处在目标阶段时,二者的指向相同
当事件流处于捕获或冒泡阶段时:currentTarget 指向当前事件活动的对象(一般为父级)
如何派发事件(dispatchEvent)?(如何进行事件广播?)
W3C: 使用 dispatchEvent 方法
IE: 使用 fireEvent 方法
var fireEvent = function(element, event){ if (document.createEventObject){ var mockEvent = document.createEventObject(); return element.fireEvent('on' + event, mockEvent) }else{ var mockEvent = document.createEvent('HTMLEvents'); mockEvent.initEvent(event, true, true); return !element.dispatchEvent(mockEvent); } }
什么是函数节流?介绍一下应用场景和原理?
函数节流(throttle)是指阻止一个函数在很短时间间隔内连续调用。
只有当上一次函数执行后达到规定的时间间隔,才能进行下一次调用。
但要保证一个累计最小调用间隔(否则拖拽类的节流都将无连续效果)
函数节流用于 onresize, onscroll 等短时间内会多次触发的事件
函数节流的原理:使用定时器做时间节流。
当触发一个事件时,先用 setTimout 让这个事件延迟一小段时间再执行。
如果在这个时间间隔内又触发了事件,就 clearTimeout 原来的定时器,
再 setTimeout 一个新的定时器重复以上流程。
函数节流简单实现:
function throttle(method, context) { clearTimeout(methor.tId); method.tId = setTimeout(function(){ method.call(context); }, 100); // 两次调用至少间隔 100ms } // 调用 window.onresize = function(){ throttle(myFunc, window); }
区分什么是“客户区坐标”、“页面坐标”、“屏幕坐标”?
客户区坐标:鼠标指针在可视区中的水平坐标(clientX)和垂直坐标(clientY)
页面坐标:鼠标指针在页面布局中的水平坐标(pageX)和垂直坐标(pageY)
屏幕坐标:设备物理屏幕的水平坐标(screenX)和垂直坐标(screenY)
如何获得一个DOM元素的绝对位置?
elem.offsetLeft:返回元素相对于其定位父级左侧的距离
elem.offsetTop:返回元素相对于其定位父级顶部的距离
elem.getBoundingClientRect():返回一个DOMRect对象,包含一组描述边框的只读属性,单位像素
分析 ['1', '2', '3'].map(parseInt) 答案是多少?
答案:[1, NaN, NaN]
parseInt(string, radix) 第2个参数 radix 表示进制。省略 radix 或 radix = 0,则数字将以十进制解析
map 每次为 parseInt 传3个参数(elem, index, array),其中 index 为数组索引
因此,map 遍历 ["1", "2", "3"],相应 parseInt 接收参数如下
parseInt('1', 0); // 1 parseInt('2', 1); // NaN parseInt('3', 2); // NaN
所以,parseInt 参数 radix 不合法,导致返回值为 NaN
new 操作符具体干了什么?
创建实例对象,this 变量引用该对象,同时还继承了构造函数的原型
属性和方法被加入到 this 引用的对象中
新创建的对象由 this 所引用,并且最后隐式的返回 this
用原生JavaScript的实现过什么功能吗?
封装选择器、调用第三方API、设置和获取样式
解释一下这段代码的意思吗?
[].forEach.call($$("*"), function(el){ el.style.outline = "1px solid #" + (~~(Math.random()*(1<<24))).toString(16); })
解释:获取页面所有的元素,遍历这些元素,为它们添加1像素随机颜色的轮廓(outline)
`$$(sel)` // $$函数被许多现代浏览器命令行支持,等价于 document.querySelectorAll(sel)
[].forEach.call(NodeLists)
// 호출 함수를 사용하여 forEach 배열 함수를 노드 요소 list[].forEach.call(NodeLists)
// 使用 call 函数将数组遍历函数 forEach 应到节点元素列表
el.style.outline = "1px solid #333"
// 样式 outline 位于盒模型之外,不影响元素布局位置
(1<<24)
// parseInt("ffffff", 16) == 16777215 == 2^24 - 1 // 1<<24 == 2^24 == 16777216
Math.random()*(1<<24)
// 表示一个位于 0 到 16777216 之间的随机浮点数
~~Math.random()*(1<<24)
// ~~
作用相当于 parseInt 取整
(~~(Math.random()*(1<<24))).toString(16)
// 转换为一个十六进制-
JavaScript实现异步编程的方法?
回调函数
事件监听
发布/订阅
Promises对象
Async函数[ES7]
web开发中会话跟踪的方法有哪些
cookie
session
url重写
隐藏input
ip地址
介绍js的基本数据类型
Undefined、Null、Boolean、Number、String
介绍js有哪些内置对象?
Object 是 JavaScript 中所有对象的父对象
数据封装类对象:Object、Array、Boolean、Number 和 String
其他对象:Function、Arguments、Math、Date、RegExp、Error
说几条写JavaScript的基本规范?
不要在同一行声明多个变量
请使用 ===/!==来比较true/false或者数值
使用对象字面量替代new Array这种形式
不要使用全局函数
Switch语句必须带有default分支
函数不应该有时候有返回值,有时候没有返回值
If语句必须使用大括号
for-in循环中的变量 应该使用var关键字明确限定作用域,从而避免作用域污
JavaScript原型,原型链 ? 有什么特点?
每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时
如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,于是就这样一直找下去,也就是我们平时所说的原型链的概念
关系:instance.constructor.prototype = instance.__proto__
로 순회합니다.
el.style.outline = "1px solid #333"
// 스타일 외곽선은 상자 모델 외부에 있으며 요소 레이아웃 위치에 영향을 주지 않습니다
(1<<24)
//parseInt("ffffff", 16) == 16777215 == 2^24 - 1 // 1<<24 == 2^24 = = 16777216Math.random()*(1<<24)
// 값을 나타냅니다. 0~16777216 임의의 부동 소수점 숫자~~Math.random()*(1<<24)
// < code>~~< /code>는parseInt 반올림(~~(Math.random()*(1<<24)과 동일합니다. )).toString (16)
// 16진수로 변환 -
콜백 함수
이벤트 수신
instance.constructor.prototype = 인스턴스.__proto__< /code >🎜🎜🎜🎜특징:🎜🎜🎜🎜🎜JavaScript 개체는 참조로 전달되며 우리가 만드는 각각의 새로운 개체 엔터티에는 자체 프로토타입 복사본이 없습니다. 프로토타입을 수정하면 이와 관련된 객체도 이 변경 사항을 상속합니다. 🎜🎜🎜🎜🎜 속성이 필요할 때 Javascript 엔진은 먼저 현재 객체에 이 속성이 있는지 확인합니다. 그렇지 않은 경우 🎜🎜🎜🎜는 Prototype 객체에 이 속성이 있는지 확인하고 객체가 검색되었습니다. . 내장 객체🎜🎜🎜🎜🎜JavaScript에는 몇 가지 유형의 값이 있나요? , 그들의 기억 지도를 그릴 수 있나요? 🎜🎜🎜🎜🎜스택: 기본 데이터 유형(정의되지 않음, Null, 부울, 숫자, 문자열) 🎜🎜🎜🎜힙: 참조 데이터 유형(객체, 배열 및 함수) 🎜🎜🎜🎜두 유형의 차이점은 저장소입니다. 위치 다릅니다. 🎜🎜🎜🎜원래 데이터 유형은 스택에 직접 저장되는 간단한 데이터 세그먼트로, 공간을 적게 차지하고 크기가 고정되어 있으므로 자주 사용되는 데이터입니다. 🎜🎜🎜 🎜참조 데이터 유형 저장 힙의 객체는 큰 공간을 차지하며 크기가 고정되어 있지 않습니다. 스택에 저장되면 프로그램 성능에 영향을 미칩니다. 참조 데이터 유형은 스택에 포인터를 저장합니다. 힙에서 엔터티의 시작 주소입니다. 인터프리터가 참조 값을 찾을 때 먼저 스택에서 🎜🎜🎜🎜 주소를 검색합니다. 주소를 얻은 후 엔터티 🎜🎜🎜🎜🎜🎜🎜🎜🎜🎜을 얻습니다. Javascript는 상속을 어떻게 구현합니까? 🎜🎜🎜🎜🎜구조적 상속🎜</li><li><p>原型继承</p></li><li><p>实例继承</p></li><li><p>拷贝继承</p></li><li><p>原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式</p></li></ul><pre class="brush:php;toolbar:false"> function Parent(){
this.name = &#39;wang&#39;;
}
function Child(){
this.age = 28;
}
Child.prototype = new Parent();//继承了Parent,通过原型
var demo = new Child();
alert(demo.age);
alert(demo.name);//得到被继承的属性
}</pre><p><strong>javascript创建对象的几种方式?</strong></p><blockquote>javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON;但写法有很多种,也能混合使用</blockquote><ul class=" list-paddingleft-2"><li><p>对象字面量的方式</p></li></ul><pre class="brush:php;toolbar:false">person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};</pre><ul class=" list-paddingleft-2"><li><p>用function来模拟无参的构造函数</p></li></ul><pre class="brush:php;toolbar:false"> function Person(){}
var person=new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class
person.name="Mark";
person.age="25";
person.work=function(){
alert(person.name+" hello...");
}
person.work();</pre><ul class=" list-paddingleft-2"><li><p>用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性)</p></li></ul><pre class="brush:php;toolbar:false">function Pet(name,age,hobby){
this.name=name;//this作用域:当前对象
this.age=age;
this.hobby=hobby;
this.eat=function(){
alert("我叫"+this.name+",我喜欢"+this.hobby+",是个程序员");
}
}
var maidou =new Pet("麦兜",25,"coding");//实例化、创建对象
maidou.eat();//调用eat方法</pre><ul class=" list-paddingleft-2"><li><p>用工厂方式来创建(内置对象)</p></li></ul><pre class="brush:php;toolbar:false">var wcDog =new Object();
wcDog.name="旺财";
wcDog.age=3;
wcDog.work=function(){
alert("我是"+wcDog.name+",汪汪汪......");
}
wcDog.work();</pre><ul class=" list-paddingleft-2"><li><p>用原型方式来创建</p></li></ul><pre class="brush:php;toolbar:false">function Dog(){
}
Dog.prototype.name="旺财";
Dog.prototype.eat=function(){
alert(this.name+"是个吃货");
}
var wangcai =new Dog();
wangcai.eat();</pre><ul class=" list-paddingleft-2"><li><p>用混合方式来创建</p></li></ul><pre class="brush:php;toolbar:false"> function Car(name,price){
this.name=name;
this.price=price;
}
Car.prototype.sell=function(){
alert("我是"+this.name+",我现在卖"+this.price+"万元");
}
var camry =new Car("凯美瑞",27);
camry.sell();</pre><p><strong>Javascript作用链域?</strong></p><ul class=" list-paddingleft-2"><li><p>全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节</p></li><li><p>当需要从局部函数查找某一属性或方法时,如果当前作用域没有找到,就会上溯到上层作用域查找</p></li><li><p>直至全局函数,这种组织形式就是作用域链</p></li></ul><p><strong>谈谈This对象的理解</strong></p><ul class=" list-paddingleft-2"><li><p>this总是指向函数的直接调用者(而非间接调用者)</p></li><li><p>如果有new关键字,this指向new出来的那个对象</p></li><li><p>在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window</p></li></ul><p><strong>eval是做什么的?</strong></p><ul class=" list-paddingleft-2"><li><p>它的功能是把对应的字符串解析成JS代码并运行</p></li><li><p>应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)</p></li><li><p>由JSON字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')')</p></li></ul><p><strong>null,undefined 的区别?</strong></p><ul class=" list-paddingleft-2"><li><p>undefined 表示不存在这个值。</p></li><li><p>undefined :是一个表示"无"的原始值或者说表示"缺少值",就是此处应该有一个值,但是还没有定义。当尝试读取时会返回 undefined</p></li><li><p>例如变量被声明了,但没有赋值时,就等于undefined</p></li><li><p>null 表示一个对象被定义了,值为“空值”</p></li><li><p>null : 是一个对象(空对象, 没有任何属性和方法)</p></li><li><p>例如作为函数的参数,表示该函数的参数不是对象;</p></li><li><p>在验证null时,一定要使用 === ,因为 == 无法分别 null 和 undefined</p></li></ul><p><strong>写一个通用的事件侦听器函数</strong></p><pre class="brush:php;toolbar:false"> // event(事件)工具集,来源:github.com/markyun
markyun.Event = {
// 页面加载完成后
readyEvent : function(fn) {
if (fn==null) {
fn=document;
}
var oldonload = window.onload;
if (typeof window.onload != &#39;function&#39;) {
window.onload = fn;
} else {
window.onload = function() {
oldonload();
fn();
};
}
},
// 视能力分别使用dom0||dom2||IE方式 来绑定事件
// 参数: 操作的元素,事件名称 ,事件处理程序
addEvent : function(element, type, handler) {
if (element.addEventListener) {
//事件类型、需要执行的函数、是否捕捉
element.addEventListener(type, handler, false);
} else if (element.attachEvent) {
element.attachEvent(&#39;on&#39; + type, function() {
handler.call(element);
});
} else {
element[&#39;on&#39; + type] = handler;
}
},
// 移除事件
removeEvent : function(element, type, handler) {
if (element.removeEventListener) {
element.removeEventListener(type, handler, false);
} else if (element.datachEvent) {
element.detachEvent(&#39;on&#39; + type, handler);
} else {
element[&#39;on&#39; + type] = null;
}
},
// 阻止事件 (主要是事件冒泡,因为IE不支持事件捕获)
stopPropagation : function(ev) {
if (ev.stopPropagation) {
ev.stopPropagation();
} else {
ev.cancelBubble = true;
}
},
// 取消事件的默认行为
preventDefault : function(event) {
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
},
// 获取事件目标
getTarget : function(event) {
return event.target || event.srcElement;
},
// 获取event对象的引用,取到事件的所有信息,确保随时能使用event;
getEvent : function(e) {
var ev = e || window.event;
if (!ev) {
var c = this.getEvent.caller;
while (c) {
ev = c.arguments[0];
if (ev && Event == ev.constructor) {
break;
}
c = c.caller;
}
}
return ev;
}
};</pre><p><strong>["1", "2", "3"].map(parseInt) 答案是多少?</strong></p><ul class=" list-paddingleft-2"><li><p>[1, NaN, NaN] 因为 parseInt 需要两个参数 (val, radix),其中 radix 表示解析时用的基数。</p></li><li><p>map 传了 3 个 (element, index, array),对应的 radix 不合法导致解析失败。</p></li></ul><p><strong>事件是?IE与火狐的事件机制有什么区别? 如何阻止冒泡?</strong></p><ul class=" list-paddingleft-2"><li><p>我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为</p></li><li><p>事件处理机制:IE是事件冒泡、Firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件</p></li><li><p>ev.stopPropagation();(旧ie的方法 ev.cancelBubble = true;)</p></li></ul><p><strong>什么是闭包(closure),为什么要用它?</strong></p><ul class=" list-paddingleft-2"><li><p>闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域</p></li><li><p>闭包的特性:</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>函数内再嵌套函数</p></li><li><p>内部函数可以引用外层的参数和变量</p></li><li><p>参数和变量不会被垃圾回收机制回收</p></li></ul></ul><p><strong>javascript 代码中的"use strict";是什么意思 ? 使用它区别是什么?</strong></p><ul class=" list-paddingleft-2"><li><p>use strict是一种ECMAscript 5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为</p></li></ul><p><strong>如何判断一个对象是否属于某个类?</strong></p><pre class="brush:php;toolbar:false">// 使用instanceof (待完善)
if(a instanceof Person){
alert(&#39;yes&#39;);
}</pre><p><strong>new操作符具体干了什么呢?</strong></p><ul class=" list-paddingleft-2"><li><p>创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型</p></li><li><p>属性和方法被加入到 this 引用的对象中</p></li><li><p>新创建的对象由 this 所引用,并且最后隐式的返回 this</p></li></ul><pre class="brush:php;toolbar:false">var obj = {};
obj.__proto__ = Base.prototype;
Base.call(obj);</pre><p><strong>js延迟加载的方式有哪些?</strong></p><ul class=" list-paddingleft-2"><li><p>defer和async、动态创建DOM方式(用得最多)、按需异步载入js</p></li></ul><p><strong>Ajax 是什么? 如何创建一个Ajax?</strong></p><blockquote>ajax的全称:Asynchronous Javascript And XML</blockquote><ul class=" list-paddingleft-2"><li><p>异步传输+js+xml</p></li><li><p>所谓异步,在这里简单地解释就是:向服务器发送请求的时候,我们不必等待结果,而是可以同时做其他的事情,等到有了结果它自己会根据设定进行后续操作,与此同时,页面是不会发生整页刷新的,提高了用户体验</p></li><li><p>创建XMLHttpRequest对象,也就是创建一个异步调用对象</p></li><li><p>建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息</p></li><li><p>设置响应HTTP请求状态变化的函数</p></li><li><p>发送HTTP请求</p></li><li><p>获取异步调用返回的数据</p></li><li><p>用JavaScript和DOM实现局部刷新</p></li></ul><p><strong>同步和异步的区别?</strong></p><ul class=" list-paddingleft-2"><li><p>同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作</p></li><li><p>异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容</p></li></ul><p><strong>异步加载JS的方式有哪些?</strong></p><ul class=" list-paddingleft-2"><li><p>defer,只支持IE</p></li><li><p>async:</p></li><li><p>创建script,插入到DOM中,加载完毕后callBack</p></li></ul><p><strong>documen.write和 innerHTML的区别</strong></p><ul class=" list-paddingleft-2"><li><p>document.write只能重绘整个页面</p></li><li><p>innerHTML可以重绘页面的一部分</p></li></ul><p><strong>DOM操作——怎样添加、移除、移动、复制、创建和查找节点?</strong></p><ul class=" list-paddingleft-2"><li><p>(1)创建新节点</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>createDocumentFragment() //创建一个DOM片段</p></li><li><p>createElement() //创建一个具体的元素</p></li><li><p>createTextNode() //创建一个文本节点</p></li></ul><li><p>(2)添加、移除、替换、插入</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>appendChild()</p></li><li><p>removeChild()</p></li><li><p>replaceChild()</p></li><li><p>insertBefore() //在已有的子节点前插入一个新的子节点</p></li></ul><li><p>(3)查找</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>getElementsByTagName() //通过标签名称</p></li><li><p>getElementsByName() // 通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)</p></li><li><p>getElementById() //通过元素Id,唯一性</p></li></ul></ul><p><strong>那些操作会造成内存泄漏?</strong></p><ul class=" list-paddingleft-2"><li><p>内存泄漏指任何对象在您不再拥有或需要它之后仍然存在</p></li><li><p>垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收</p></li><li><p>setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏</p></li><li><p>闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)</p></li></ul><p><strong>渐进增强和优雅降级</strong></p><ul class=" list-paddingleft-2"><li><p>渐进增强 :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。</p></li><li><p>优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容</p></li></ul><p><strong>Javascript垃圾回收方法</strong></p><ul class=" list-paddingleft-2"><li><p>标记清除(mark and sweep)</p></li></ul><blockquote><ul class=" list-paddingleft-2"><li><p>这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”</p></li><li><p>垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了</p></li></ul></blockquote><p><strong>引用计数(reference counting)</strong></p><blockquote>在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间</blockquote><p><strong>js继承方式及其优缺点</strong></p><ul class=" list-paddingleft-2"><li><p>原型链继承的缺点</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>一是字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。</p></li></ul><li><p>借用构造函数(类式继承)</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起。所以我们需要原型链+借用构造函数的模式,这种模式称为组合继承</p></li></ul><li><p>组合式继承</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>组合式继承是比较常用的一种继承方法,其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又保证每个实例都有它自己的属性。</p></li></ul></ul><p><strong>defer和async</strong></p><ul class=" list-paddingleft-2"><li><p>defer并行加载js文件,会按照页面上script标签的顺序执行async并行加载js文件,下载完成立即执行,不会按照页面上script标签的顺序执行</p></li></ul><p><strong>用过哪些设计模式?</strong></p><ul class=" list-paddingleft-2"><li><p>工厂模式:</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位置防止代码重复</p></li><li><p>工厂模式解决了重复实例化的问题 ,但还有一个问题,那就是识别问题,因为根本无法 搞清楚他们到底是哪个对象的实例</p></li></ul></ul><p>-</p><pre class="brush:php;toolbar:false">function createObject(name,age,profession){//集中实例化的函数var obj = new Object();
obj.name = name;
obj.age = age;
obj.profession = profession;
obj.move = function () {
return this.name + &#39; at &#39; + this.age + &#39; engaged in &#39; + this.profession;
};
return obj;
}
var test1 = createObject(&#39;trigkit4&#39;,22,&#39;programmer&#39;);//第一个实例var test2 = createObject(&#39;mike&#39;,25,&#39;engineer&#39;);//第二个实例</pre><ul class=" list-paddingleft-2"><li><p>构造函数模式</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>使用构造函数的方法 ,即解决了重复实例化的问题 ,又解决了对象识别的问题,该模式与工厂模式的不同之处在于</p></li></ul><li><p>构造函数方法没有显示的创建对象 (new Object());</p></li><li><p>直接将属性和方法赋值给 this 对象;</p></li><li><p>没有 renturn 语句</p></li></ul><p><strong>说说你对闭包的理解</strong></p><ul class=" list-paddingleft-2"><li><p>使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念</p></li><li><p>闭包有三个特性:</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>1.函数嵌套函数</p></li><li><p>2.函数内部可以引用外部的参数和变量</p></li><li><p>3.参数和变量不会被垃圾回收机制回收</p></li></ul></ul><p><strong>请解释一下 JavaScript 的同源策略</strong></p><ul class=" list-paddingleft-2"><li><p>概念:同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议</p></li><li><p>指一段脚本只能读取来自同一来源的窗口和文档的属性</p></li></ul><p><strong>为什么要有同源限制?</strong></p><ul class=" list-paddingleft-2"><li><p>我们举例说明:比如一个黑客程序,他利用Iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript读取到你的表单中input中的内容,这样用户名,密码就轻松到手了。</p></li><li><p>缺点</p></li><ul class=" list-paddingleft-2" style="list-style-type: square;"><li><p>现在网站的JS都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节</p></li></ul></ul><p><strong>实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制</strong></p><pre class="brush:php;toolbar:false">Object.prototype.clone = function(){
var o = this.constructor === Array ? [] : {};
for(var e in this){
o[e] = typeof this[e] === "object" ? this[e].clone() : this[e];
}
return o;
}</pre><p><strong>说说严格模式的限制</strong></p><ul class=" list-paddingleft-2"><li><p>严格模式主要有以下限制:</p></li><li><p>变量必须声明后再使用</p></li><li><p>函数的参数不能有同名属性,否则报错</p></li><li><p>不能使用with语句</p></li><li><p>不能对只读属性赋值,否则报错</p></li><li><p>不能使用前缀0表示八进制数,否则报错</p></li><li><p>不能删除不可删除的属性,否则报错</p></li><li><p>不能删除变量delete prop,会报错,只能删除属性delete global[prop]</p></li><li><p>eval不会在它的外层作用域引入变量</p></li><li><p>eval和arguments不能被重新赋值</p></li><li><p>arguments不会自动反映函数参数的变化</p></li><li><p>不能使用arguments.callee</p></li><li><p>不能使用arguments.caller</p></li><li><p>禁止this指向全局对象</p></li><li><p>不能使用fn.caller和fn.arguments获取函数调用的堆栈</p></li><li><p>增加了保留字(比如protected、static和interface)</p></li></ul><p><strong>如何删除一个cookie</strong></p><ul class=" list-paddingleft-2"><li><p>将时间设为当前时间往前一点</p></li></ul><pre class="brush:php;toolbar:false">var date = new Date();
date.setDate(date.getDate() - 1);//真正的删除</pre><p>setDate()方法用于设置一个月的某一天</p><ul class=" list-paddingleft-2"><li><p>expires的设置</p></li></ul><pre class="brush:php;toolbar:false"> document.cookie = &#39;user=&#39;+ encodeURIComponent(&#39;name&#39;) + &#39;;expires = &#39; + new Date(0)</pre><p><strong>编写一个方法 求一个字符串的字节长度</strong></p><ul class=" list-paddingleft-2"><li><p>假设:一个英文字符占用一个字节,一个中文字符占用两个字节</p></li></ul><pre class="brush:php;toolbar:false">function GetBytes(str){
var len = str.length;
var bytes = len;
for(var i=0; i<len; i++){
if (str.charCodeAt(i) > 255) bytes++;
}
return bytes;
}
alert(GetBytes("你好,as"));</pre>
<p><strong>请解释什么是事件代理</strong></p>
<ul class=" list-paddingleft-2"><li><p>事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能</p></li></ul>
<p><strong>attribute和property的区别是什么?</strong></p>
<ul class=" list-paddingleft-2">
<li><p>attribute是dom元素在文档中作为html标签拥有的属性;</p></li>
<li><p>property就是dom元素在js中作为对象拥有的属性。</p></li>
<li><p>对于html的标准属性来说,attribute和property是同步的,是会自动更新的</p></li>
<li><p>但是对于自定义的属性来说,他们是不同步的</p></li>
</ul>
<p><strong>页面编码和被请求的资源编码如果不一致如何处理?</strong></p>
<ul class=" list-paddingleft-2">
<li><p>后端响应头设置 charset</p></li>
<li><p>前端页面<code><meta>
设置 charset把<script>
放在</body>
之前和之后有什么区别?浏览器会如何解析它们?
按照HTML标准,在</body>
结束后出现<script>
或任何元素的开始标签,都是解析错误
虽然不符合HTML标准,但浏览器会自动容错,使实际效果与写在</body>
之前没有区别
浏览器的容错机制会忽略<script>之前的</body>
,视作<script>
仍在 body 体内。省略</body>
和</html>
闭合标签符合HTML标准,服务器可以利用这一标准尽可能少输出内容
延迟加载JS的方式有哪些?
设置<script>
属性 defer="defer" (脚本将在页面完成解析时执行)
动态创建 script DOM:document.createElement('script');
XmlHttpRequest 脚本注入
延迟加载工具 LazyLoad
异步加载JS的方式有哪些?
设置<script>
属性 async="async" (一旦脚本可用,则会异步执行)
动态创建 script DOM:document.createElement('script');
XmlHttpRequest 脚本注入
异步加载库 LABjs
模块加载器 Sea.js
JavaScript 中,调用函数有哪几种方式?
方法调用模式 Foo.foo(arg1, arg2);
函数调用模式 foo(arg1, arg2);
构造器调用模式 (new Foo())(arg1, arg2);
call/applay调用模式 Foo.foo.call(that, arg1, arg2);
bind调用模式 Foo.foo.bind(that)(arg1, arg2)();
简单实现 Function.bind 函数?
if (!Function.prototype.bind) { Function.prototype.bind = function(that) { var func = this, args = arguments; return function() { return func.apply(that, Array.prototype.slice.call(args, 1)); } } } // 只支持 bind 阶段的默认参数: func.bind(that, arg1, arg2)(); // 不支持以下调用阶段传入的参数: func.bind(that)(arg1, arg2);
列举一下JavaScript数组和对象有哪些原生方法?
数组:
arr.concat(arr1, arr2, arrn);
arr.join(",");
arr.sort(func);
arr.pop();
arr.push(e1, e2, en);
arr.shift();
unshift(e1, e2, en);
arr.reverse();
arr.slice(start, end);
arr.splice(index, count, e1, e2, en);
arr.indexOf(el);
arr.includes(el); // ES6
对象:
object.hasOwnProperty(prop);
object.propertyIsEnumerable(prop);
object.valueOf();
object.toString();
object.toLocaleString();
Class.prototype.isPropertyOf(object);
Array.splice() 与 Array.splice() 的区别?
slice -- “读取”数组指定的元素,不会对原数组进行修改
语法:arr.slice(start, end)
start 指定选取开始位置(含)
end 指定选取结束位置(不含)
splice
“操作”数组指定的元素,会修改原数组,返回被删除的元素
语法:arr.splice(index, count, [insert Elements])
index 是操作的起始位置
count = 0 插入元素,count > 0 删除元素
[insert Elements] 向数组新插入的元素
JavaScript 对象生命周期的理解?
当创建一个对象时,JavaScript 会自动为该对象分配适当的内存
垃圾回收器定期扫描对象,并计算引用了该对象的其他对象的数量
如果被引用数量为 0,或惟一引用是循环的,那么该对象的内存即可回收
哪些操作会造成内存泄漏?
JavaScript 内存泄露指对象在不需要使用它时仍然存在,导致占用的内存不能使用或回收
未使用 var 声明的全局变量
闭包函数(Closures)
循环引用(两个对象相互引用)
控制台日志(console.log)
移除存在绑定事件的DOM元素(IE)
위 내용은 JavaScript - 개인 기사 Sifou의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!