首頁 >web前端 >js教程 >JavaScript - 個人文章 思否

JavaScript - 個人文章 思否

不言
不言原創
2018-04-02 17:37:322681瀏覽

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(Same origin policy)是一種約定,由Netscape公司1995年引進瀏覽器,它是瀏覽器最核心也最基本的安全功能,如果缺少了同源策略,瀏覽器很容易受到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>
    <script>
        document.domain = 'domain.com';
        // 获取父窗口中变量
        alert('get js data from parent ---> ' + window.parent.user);
    </script>
    • 弊端:請看下面渲染載入最佳化

    • 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   ---> target目標----> document

  • 由此,addEventListener的第三個參數設定為true和false的差異已經非常清楚了:

    • #true表示該元素在事件的「捕獲階段」(由外往內傳遞時)回應事件;

    • false表示該元素在事件的「冒泡階段」(由內向外傳遞時)回應事件。

JS 判斷裝置來源

function deviceType(){
    var ua = navigator.userAgent;
    var agent = ["Android", "iPhone", "SymbianOS", "Windows Phone", "iPad", "iPod"];    
    for(var i=0; i<len,len = agent.length; i++){
        if(ua.indexOf(agent[i])>0){         
            break;
        }
    }
}
deviceType();
window.addEventListener('resize', function(){
    deviceType();
})


//微信的 有些不太一样
function isWeixin(){
    var ua = navigator.userAgent.toLowerCase();
    if(ua.match(/MicroMessenger/i)=='micromessenger'){
        return true;
    }else{
        return false;
    }
}

JavaScript的組成

  • JavaScript 由以下三個部分組成:

    • ECMAScript(核心):JavaScript 語言基礎

    • DOM(文件物件模型):規定了存取HTML和XML的介面

    • BOM(瀏覽器物件模型):提供了瀏覽器視窗之間進行互動的物件與方法

JS的基本資料型別與引用資料型別

  • 基本資料型別:undefined、null、boolean、number、string、symbol

  • 引用資料型態:object、array、function

#偵測瀏覽器版本版本有哪些方式?

  • 根據navigator.userAgent   //  UA.toLowerCase().indexOf('chrome')

  • 根據window 物件的成員// 'ActiveXObject' in window

介紹JS有哪些內建物件?

  • 資料封裝類別物件:Object、Array、Boolean、Number、String

  • 其他物件:Function、Arguments、Math、 Date、RegExp、Error

  • ES6新增物件:Symbol、Map、Set、Promises、Proxy、Reflect

#說幾條寫JavaScript的基本規格?

  • 程式碼縮進,建議使用「四個空格」縮排

  • 程式碼片段使用花括號{}包裹

  • 語句結束使用分號;

  • 變數和函數在使用前進行宣告

  • #以大寫字母一開始命名建構函數,全大寫命名常數

  • 規格定義JSON對象,補全雙引號

  • 用{}和[]聲明物件與陣列

如何寫高效能的JavaScript?

  • 遵循嚴格模式:"use strict";

  • 將js腳本放在頁面底部,加快渲染頁面

  • 將js腳本將腳本成群組打包,減少請求

  • #使用非阻塞方式下載js腳本

  • 盡量使用局部變數來保存全域變數

  • 盡量減少使用閉包

  • #使用window 物件屬性方法時,省略window

  • 盡量減少物件成員巢狀

  • 快取DOM 節點的存取

  • 透過避免使用eval()和Function() 建構子

  • 給setTimeout() 和setInterval() 傳遞函數而不是字串作為參數

  • ##盡量使用直接量建立物件和陣列
  • 最小化重繪(repaint)和回流(reflow)
描述瀏覽器的渲染過程, DOM樹和渲染樹的差別?

    瀏覽器的渲染過程:
    • 解析HTML建置DOM(DOM樹),並行請求css/image/js

    • CSS 檔案下載完成,開始建置CSSOM(CSS樹)

    • CSSOM 建置結束後,和DOM 一起產生Render Tree(渲染樹)

    • ##版面(Layout):計算出每個節點在螢幕中的位置

    • 顯示(Painting):透過顯示卡把頁畫到螢幕上

    ##DOM樹和渲染樹的差異:
    • DOM樹與HTML標籤一一對應,包含head與隱藏元素
    • ##渲染樹不包含head和隱藏元素,大段文字的每一個行都是獨立節點,每個節點都有對應的css屬性
    #重繪和回流(重排)的區別和關係?

重繪:當渲染樹中的元素外觀(如:顏色)改變,不影響佈局時,產生重繪
  • #回流:當渲染樹中的元素的佈局(如:尺寸、位置、隱藏/狀態狀態)改變時,產生重繪回流
  • 注意:JS取得Layout屬性值(如:offsetLeft、scrollTop、getComputedStyle等)也會造成回流。因為瀏覽器需要透過回流計算最新值
  • 回流必將引起重繪,而重繪不一定會造成回流
  • 如何最小化重繪(repaint)和回流(reflow)?

需要要對元素進行複雜的操作時,可以先隱藏(display:"none"),操作完成後再顯示
  • 需要建立多個DOM節點時,使用DocumentFragment建立完後一次性的加入document
  • 快取Layout屬性值,如:var left = elem.offsetLeft; 這樣,多次使用left 只產生一次回流
  • 盡量避免用table佈局(table元素一旦觸發回流就會導致table裡所有的其它元素回流)
  • 避免使用css表達式(expression),因為每次呼叫都會重新計算值(包括載入頁面)
  • 盡量使用css 屬性簡寫,如:用border 取代border- width, border-style, border-color
  • 批次修改元素樣式:elem.className 和elem.style.cssText 取代elem.style.xxx
  • #script 的位置是否會影響首屏顯示時間?

在解析 HTML 產生 DOM 過程中,js 檔案的下載是並行的,不需要 DOM 處理到 script 節點。因此,script的位置不會影響首屏顯示的開始時間。
  • 瀏覽器解析HTML 是自上而下的線性過程,script作為HTML 的一部分同樣遵循這個原則
  • 因此,script 會延遲DomContentLoad,只顯示其上部分首屏內容,從而影響首屏顯示的完成時間
  • #解釋JavaScript中的作用域與變數宣告提升?

JavaScript作用域:
  • #在Java、C等語言中,作用域為for語句、if語句或{}內的一塊區域,稱為作用域;
    • 而在JavaScript 中,作用域為function(){}內的區域,稱為函數作用域。
    • JavaScript變數宣告提升:
  • #在JavaScript中,函數宣告與變數宣告經常被JavaScript引擎隱含地提升到目前作用域的頂端。
    • 宣告語句中的賦值部分並不會被提升,只有名稱被提升
    • 函數宣告的優先權高於變量,如果變數名稱跟函數名稱相同且未賦值,則函數宣告會覆寫變數宣告
    • 如果函數有多個同名參數,那麼最後一個參數(即使沒有定義)會覆寫前面的同名參數
    介紹JavaScript的原型,原型鏈?有什麼特點?

原型:
  • #JavaScript的所有物件中都包含了一個[__proto__] 內部屬性,這個屬性所對應的就是該物件的原型
    • JavaScript的函數對象,除了原型[__proto__] 之外,也預設了prototype 屬性
    • 當函數物件以建構函式建立實例時,該prototype 屬性值將會被當作實例物件的原型[__proto__]。
    • 原型鏈:
  • #當一個物件呼叫的屬性/方法本身不存在時,就會去自己[__proto__] 關聯的前輩prototype 物件上去找
    • 如果沒找到,就會去該prototype 原型[__proto__] 關聯的前輩prototype 去找。依序類別推,直到找到屬性/方法或 undefined 為止。從而形成了所謂的「原型鏈」
  • 原型特点:

    • 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)


    1. `$$(sel)` // $$函数被许多现代浏览器命令行支持,等价于 document.querySelectorAll(sel)


    1. [].forEach.call(NodeLists) // 使用call 函數將陣列遍歷函數forEach 應到節點元素清單


    1. #el.style.outline = "1px solid #333" // 樣式outline 位於盒子模型之外,不影響元素佈局位置


    1. #(1<<24 ) // parseInt("ffffff", 16) == 16777215 == 2^24 - 1 // 1<<24 == 2^24 == 167777216




#1

  • #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 - 個人文章 思否JavaScript原型,原型鏈? 有什麼特色?

每個物件都會在其內部初始化一個屬性,就是prototype(原型),當我們存取一個物件的屬性時

  • 如果這個物件內部不存在這個屬性,那麼他就會去prototype裡找這個屬性,這個prototype又會有自己的prototype,於是就這樣一直找下去,也就是我們平常所說的原型鏈的概念

    #########關係:###instance.constructor.prototype = instance.__proto__###############特徵:######### #######JavaScript物件是透過引用來傳遞的,我們所建立的每個新物件實體中並沒有一份屬於自己的原型副本。當我們修改原型時,與之相關的物件也會繼承這項改變。 ###############當我們需要一個屬性的時,Javascript引擎會先看目前物件中是否有這個屬性, 如果沒有的########### #就會找他的Prototype物件是否有這個屬性,如此遞推下去,一直檢索到Object 內建物件###############JavaScript有幾種類型的值? ,你能畫一下他們的記憶圖嗎? ################堆疊:原始資料型別(Undefined,Null,Boolean,Number、String)############堆:引用資料型態(對象、陣列和函數)############兩種類型的區別是:儲存位置不同;############原始資料型別直接儲存在堆疊(stack)中的簡單數據段,佔據空間小、大小固定,屬於被頻繁使用數據,所以放入棧​​中存儲;############引用數據類型存儲在堆(heap)中的對象,佔據空間大、大小不固定,如果儲存在堆疊中,將會影響程式運作的效能;引用資料型別在堆疊中儲存了指針,該指標指向堆疊中該實體的起始位址。當解釋器尋找參考值時,會先檢索其############在堆疊中的位址,取得位址後會從堆疊中取得實體############ ##################Javascript如何實作繼承? ###############建構繼承###
  • 原型继承

  • 实例继承

  • 拷贝继承

  • 原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式

 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);//得到被继承的属性
  }

javascript创建对象的几种方式?

javascript创建对象简单的说,无非就是使用内置对象或各种自定义对象,当然还可以用JSON;但写法有很多种,也能混合使用
  • 对象字面量的方式

person={firstname:"Mark",lastname:"Yun",age:25,eyecolor:"black"};
  • 用function来模拟无参的构造函数

 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();
  • 用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性)

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方法
  • 用工厂方式来创建(内置对象)

var wcDog =new Object();
     wcDog.name="旺财";
     wcDog.age=3;
     wcDog.work=function(){
       alert("我是"+wcDog.name+",汪汪汪......");
     }
     wcDog.work();
  • 用原型方式来创建

function Dog(){

     }
     Dog.prototype.name="旺财";
     Dog.prototype.eat=function(){
     alert(this.name+"是个吃货");
     }
     var wangcai =new Dog();
     wangcai.eat();
  • 用混合方式来创建

 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();

Javascript作用链域?

  • 全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节

  • 当需要从局部函数查找某一属性或方法时,如果当前作用域没有找到,就会上溯到上层作用域查找

  • 直至全局函数,这种组织形式就是作用域链

谈谈This对象的理解

  • this总是指向函数的直接调用者(而非间接调用者)

  • 如果有new关键字,this指向new出来的那个对象

  • 在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window

eval是做什么的?

  • 它的功能是把对应的字符串解析成JS代码并运行

  • 应该避免使用eval,不安全,非常耗性能(2次,一次解析成js语句,一次执行)

  • 由JSON字符串转换为JSON对象的时候可以用eval,var obj =eval('('+ str +')')

null,undefined 的区别?

  • undefined 表示不存在这个值。

  • undefined :是一个表示"无"的原始值或者说表示"缺少值",就是此处应该有一个值,但是还没有定义。当尝试读取时会返回 undefined

  • 例如变量被声明了,但没有赋值时,就等于undefined

  • null 表示一个对象被定义了,值为“空值”

  • null : 是一个对象(空对象, 没有任何属性和方法)

  • 例如作为函数的参数,表示该函数的参数不是对象;

  • 在验证null时,一定要使用 === ,因为 == 无法分别 null 和 undefined

写一个通用的事件侦听器函数

 // 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;
        }
    };

["1", "2", "3"].map(parseInt) 答案是多少?

  • [1, NaN, NaN] 因为 parseInt 需要两个参数 (val, radix),其中 radix 表示解析时用的基数。

  • map 传了 3 个 (element, index, array),对应的 radix 不合法导致解析失败。

事件是?IE与火狐的事件机制有什么区别? 如何阻止冒泡?

  • 我们在网页中的某个操作(有的操作对应多个事件)。例如:当我们点击一个按钮就会产生一个事件。是可以被 JavaScript 侦测到的行为

  • 事件处理机制:IE是事件冒泡、Firefox同时支持两种事件模型,也就是:捕获型事件和冒泡型事件

  • ev.stopPropagation();(旧ie的方法 ev.cancelBubble = true;)

什么是闭包(closure),为什么要用它?

  • 闭包是指有权访问另一个函数作用域中变量的函数,创建闭包的最常见的方式就是在一个函数内创建另一个函数,通过另一个函数访问这个函数的局部变量,利用闭包可以突破作用链域

  • 闭包的特性:

    • 函数内再嵌套函数

    • 内部函数可以引用外层的参数和变量

    • 参数和变量不会被垃圾回收机制回收

javascript 代码中的"use strict";是什么意思 ? 使用它区别是什么?

  • use strict是一种ECMAscript 5 添加的(严格)运行模式,这种模式使得 Javascript 在更严格的条件下运行,使JS编码更加规范化的模式,消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为

如何判断一个对象是否属于某个类?

// 使用instanceof (待完善)
   if(a instanceof Person){
       alert(&#39;yes&#39;);
   }

new操作符具体干了什么呢?

  • 创建一个空对象,并且 this 变量引用该对象,同时还继承了该函数的原型

  • 属性和方法被加入到 this 引用的对象中

  • 新创建的对象由 this 所引用,并且最后隐式的返回 this

var obj  = {};
obj.__proto__ = Base.prototype;
Base.call(obj);

js延迟加载的方式有哪些?

  • defer和async、动态创建DOM方式(用得最多)、按需异步载入js

Ajax 是什么? 如何创建一个Ajax?

ajax的全称:Asynchronous Javascript And XML
  • 异步传输+js+xml

  • 所谓异步,在这里简单地解释就是:向服务器发送请求的时候,我们不必等待结果,而是可以同时做其他的事情,等到有了结果它自己会根据设定进行后续操作,与此同时,页面是不会发生整页刷新的,提高了用户体验

  • 创建XMLHttpRequest对象,也就是创建一个异步调用对象

  • 建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息

  • 设置响应HTTP请求状态变化的函数

  • 发送HTTP请求

  • 获取异步调用返回的数据

  • 用JavaScript和DOM实现局部刷新

同步和异步的区别?

  • 同步:浏览器访问服务器请求,用户看得到页面刷新,重新发请求,等请求完,页面刷新,新内容出现,用户看到新内容,进行下一步操作

  • 异步:浏览器访问服务器请求,用户正常操作,浏览器后端进行请求。等请求完,页面不刷新,新内容也会出现,用户看到新内容

异步加载JS的方式有哪些?

  • defer,只支持IE

  • async:

  • 创建script,插入到DOM中,加载完毕后callBack

documen.write和 innerHTML的区别

  • document.write只能重绘整个页面

  • innerHTML可以重绘页面的一部分

DOM操作——怎样添加、移除、移动、复制、创建和查找节点?

  • (1)创建新节点

    • createDocumentFragment() //创建一个DOM片段

    • createElement() //创建一个具体的元素

    • createTextNode() //创建一个文本节点

  • (2)添加、移除、替换、插入

    • appendChild()

    • removeChild()

    • replaceChild()

    • insertBefore() //在已有的子节点前插入一个新的子节点

  • (3)查找

    • getElementsByTagName() //通过标签名称

    • getElementsByName() // 通过元素的Name属性的值(IE容错能力较强,会得到一个数组,其中包括id等于name值的)

    • getElementById() //通过元素Id,唯一性

那些操作会造成内存泄漏?

  • 内存泄漏指任何对象在您不再拥有或需要它之后仍然存在

  • 垃圾回收器定期扫描对象,并计算引用了每个对象的其他对象的数量。如果一个对象的引用数量为 0(没有其他对象引用过该对象),或对该对象的惟一引用是循环的,那么该对象的内存即可回收

  • setTimeout 的第一个参数使用字符串而非函数的话,会引发内存泄漏

  • 闭包、控制台日志、循环(在两个对象彼此引用且彼此保留时,就会产生一个循环)

渐进增强和优雅降级

  • 渐进增强 :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行效果、交互等改进和追加功能达到更好的用户体验。

  • 优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容

Javascript垃圾回收方法

  • 标记清除(mark and sweep)

  • 这是JavaScript最常见的垃圾回收方式,当变量进入执行环境的时候,比如函数中声明一个变量,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候(函数执行结束)将其标记为“离开环境”

  • 垃圾回收器会在运行的时候给存储在内存中的所有变量加上标记,然后去掉环境中的变量以及被环境中变量所引用的变量(闭包),在这些完成之后仍存在标记的就是要删除的变量了

引用计数(reference counting)

在低版本IE中经常会出现内存泄露,很多时候就是因为其采用引用计数方式进行垃圾回收。引用计数的策略是跟踪记录每个值被使用的次数,当声明了一个 变量并将一个引用类型赋值给该变量的时候这个值的引用次数就加1,如果该变量的值变成了另外一个,则这个值得引用次数减1,当这个值的引用次数变为0的时 候,说明没有变量在使用,这个值没法被访问了,因此可以将其占用的空间回收,这样垃圾回收器会在运行的时候清理掉引用次数为0的值占用的空间

js继承方式及其优缺点

  • 原型链继承的缺点

    • 一是字面量重写原型会中断关系,使用引用类型的原型,并且子类型还无法给超类型传递参数。

  • 借用构造函数(类式继承)

    • 借用构造函数虽然解决了刚才两种问题,但没有原型,则复用无从谈起。所以我们需要原型链+借用构造函数的模式,这种模式称为组合继承

  • 组合式继承

    • 组合式继承是比较常用的一种继承方法,其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又保证每个实例都有它自己的属性。

defer和async

  • defer并行加载js文件,会按照页面上script标签的顺序执行async并行加载js文件,下载完成立即执行,不会按照页面上script标签的顺序执行

用过哪些设计模式?

  • 工厂模式:

    • 主要好处就是可以消除对象间的耦合,通过使用工程方法而不是new关键字。将所有实例化的代码集中在一个位置防止代码重复

    • 工厂模式解决了重复实例化的问题 ,但还有一个问题,那就是识别问题,因为根本无法 搞清楚他们到底是哪个对象的实例

-

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;);//第二个实例
  • 构造函数模式

    • 使用构造函数的方法 ,即解决了重复实例化的问题 ,又解决了对象识别的问题,该模式与工厂模式的不同之处在于

  • 构造函数方法没有显示的创建对象 (new Object());

  • 直接将属性和方法赋值给 this 对象;

  • 没有 renturn 语句

说说你对闭包的理解

  • 使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。在js中,函数即闭包,只有函数才会产生作用域的概念

  • 闭包有三个特性:

    • 1.函数嵌套函数

    • 2.函数内部可以引用外部的参数和变量

    • 3.参数和变量不会被垃圾回收机制回收

请解释一下 JavaScript 的同源策略

  • 概念:同源策略是客户端脚本(尤其是Javascript)的重要的安全度量标准。它最早出自Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载。这里的同源策略指的是:协议,域名,端口相同,同源策略是一种安全协议

  • 指一段脚本只能读取来自同一来源的窗口和文档的属性

为什么要有同源限制?

  • 我们举例说明:比如一个黑客程序,他利用Iframe把真正的银行登录页面嵌到他的页面上,当你使用真实的用户名,密码登录时,他的页面就可以通过Javascript读取到你的表单中input中的内容,这样用户名,密码就轻松到手了。

  • 缺点

    • 现在网站的JS都会进行压缩,一些文件用了严格模式,而另一些没有。这时这些本来是严格模式的文件,被 merge后,这个串就到了文件的中间,不仅没有指示严格模式,反而在压缩后浪费了字节

实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制

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;
    }

说说严格模式的限制

  • 严格模式主要有以下限制:

  • 变量必须声明后再使用

  • 函数的参数不能有同名属性,否则报错

  • 不能使用with语句

  • 不能对只读属性赋值,否则报错

  • 不能使用前缀0表示八进制数,否则报错

  • 不能删除不可删除的属性,否则报错

  • 不能删除变量delete prop,会报错,只能删除属性delete global[prop]

  • eval不会在它的外层作用域引入变量

  • eval和arguments不能被重新赋值

  • arguments不会自动反映函数参数的变化

  • 不能使用arguments.callee

  • 不能使用arguments.caller

  • 禁止this指向全局对象

  • 不能使用fn.caller和fn.arguments获取函数调用的堆栈

  • 增加了保留字(比如protected、static和interface)

如何删除一个cookie

  • 将时间设为当前时间往前一点

var date = new Date();

date.setDate(date.getDate() - 1);//真正的删除

setDate()方法用于设置一个月的某一天

  • expires的设置

  document.cookie = &#39;user=&#39;+ encodeURIComponent(&#39;name&#39;)  + &#39;;expires = &#39; + new Date(0)

编写一个方法 求一个字符串的字节长度

  • 假设:一个英文字符占用一个字节,一个中文字符占用两个字节

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"));

请解释什么是事件代理

  • 事件代理(Event Delegation),又称之为事件委托。是 JavaScript 中常用绑定事件的常用技巧。顾名思义,“事件代理”即是把原本需要绑定的事件委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的事件冒泡。使用事件代理的好处是可以提高性能

attribute和property的区别是什么?

  • attribute是dom元素在文档中作为html标签拥有的属性;

  • property就是dom元素在js中作为对象拥有的属性。

  • 对于html的标准属性来说,attribute和property是同步的,是会自动更新的

  • 但是对于自定义的属性来说,他们是不同步的

页面编码和被请求的资源编码如果不一致如何处理?

  • 后端响应头设置 charset

  • 前端页面<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 - 個人文章 思否的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn