搜尋
首頁web前端js教程一些常用的JavaScript 知識點整理

JavaScript是依照ECMAScript標準設計實作的,後面說的JavaScript語法其實是ES5的標準的實作。

先說有哪些基礎語法?

最基礎語法有哪些?

基礎語法幾乎所有的語言差異不大,無非資料型別運算子控制語句函數等,簡單列舉。

5種基本資料型別& 1種複雜的資料型別

JavaScript包含5種基本資料型別,分別是Undefined / Null / Boolean / Number / String ,基本資料型就這五種,沒有其他的!

JavaScript包含1種複雜的資料型別,就是 Object 類型, Object 類型是所有其他物件的基底類別。

注意:JavaScript不區分浮點數和整數,都是用 Number 來表示。

前面提到的5種基本資料類型,以及這兒的1種複雜資料類型,這就是資料類型的全部了!

基本運算子

這個是常識,知道怎麼回事就好。

常用的運算子包括:算術運算子、關聯運算子、布林運算子、賦值運算子等。

控制語句

這就是我們常說的if-else之類的控制語句。

常用的不多:if語句、switch語句for語句while語句、for-in語句。

函數

函數就是一小段邏輯的封裝,理論上邏輯越獨立越好。

JavaScript函數相對其他語言來說有很大不同。 JavaScript函數既可以當作參數,也可以當作傳回值。

此外JavaScript函數可以接受任意數量的參數,並且可以透過arguments物件來存取這些參數。

任何一門語言的基礎語法都是相通的,除開一些細節差異,大致就是上面這些了:資料型別、運算子、控制語句、函數、模組等等。

接下來介紹稍微複雜的一些概念。

變數、作用域、記憶體問題

變數

JavaScript變數分為兩種:基本型別和參考型別。其中基本型別就是前面提到的5種基本資料型別,引用型別就是前面提到的 Object 以及其他基於它的複雜資料型別。

✦ 基本型別:在記憶體中佔據實際大小的空間,賦值的時候,會在記憶體中建立一份新的副本。保存在 棧記憶體 中。

✦ 引用類型:指向物件的指標而不是物件本身,賦值的時候,只是創建了一個新的指標指向物件。儲存在 堆記憶體 中。

一些常用的JavaScript 知識點整理

變數記憶體分配

一句話就是,基本型別在記憶體中是實際的值;而引用型別在記憶體中就是一個指針,指向一個對象,多個引用類型可能同時指向同一個對象。

那麼,要如何確定某個變數是哪一種資料型別呢?

確定一個變數是哪一種基本型別用typeof運算子。

確定一個變數是哪一種參考型別用instanceof運算子。

這個別忘了!

作用域

變數是在某個特定的作用域中宣告的,作用域決定了這些變數的生命週期,以及哪些程式碼可以存取其中的變數。

JavaScript作用域只包含全域作用域和函數作用域,不包含區塊層級作用域!

作用域是可以嵌套的,從而形成作用域鏈。由於作用域鏈的存在,可以讓變數的查找向上追溯,即子函數可以存取父函數的作用域=>祖先函數的作用域=>直到全域作用域,我們也稱為閉包,後文會介紹。

var color = "blue"; function changeColor() { var anotherColor = "red"; function swapColors() { var tempColor = anotherColor;
        anotherColor = color;
        color = tempColor; // 这里可以访问color、anotherColor、tempColor  } // 这里可以访问color、anotherColor,但不能访问tempColor swapColors();
} // 这里只能访问color、changeColor();

如下圖所示,每個作用域能夠存取到的變數以及嵌套的作用域可向上追溯。

一些常用的JavaScript 知識點整理

作用域鏈

作用域的概念看著簡單,實際使用會有不少問題,遇到問題要細心分析。

記憶體問題

JavaScript引擎具有自動垃圾回收機制,不需要太關注記憶體分配和垃圾回收問題。這兒就不展開了!

引用型別

前面提過,Object是唯一的複雜資料型別,引用型別都是從Object型別繼承而來。

Array:陣列類型

Date:日期類型

✦ RegExp:正規表示式類型,這個多學有好處!

✦ 等等...

那问题来了,我们用的最多的函数是什么数据类型呢?答案是Function类型!

诶,好像发现了点什么东西?由于Function是引用类型,而JavaScript又可以往引用类型上加属性和方法。那么,函数也可以!这也是JavaScript函数强大和复杂的地方。也就是说:函数也可以拥有自定义方法和属性!

此外,JavaScript对前面提到的5种基本类型的其中3种也做了引用类型封装,分别是Boolean、Number、String,但其实使用不多,了解就行。

对了,在所有代码执行之前,作用域就内置了两个对象,分别是Global和Math,其中浏览器的Global就是window啦!

到此为止,JavaScript中基础的概念都差不多介绍了,其中函数和作用域相对来说复杂一些,其他的都比较浅显。

接下来,我会介绍介绍JavaScript中一些稍微复杂一些的概念:面向对象

面向对象编程

JavaScript本身并没有类和接口的概念了,面向对象都是基于原型实现的。

为了简单,我们只分析面向对象的两个问题:

✦ 如何定义一个类?

✦ 如何实现类的继承

定义一个类

不扯其他的,直接告诉你。我们使用构造函数+原型的方式来定义一个类。

使用构造函数创建自定义类型,然后使用new操作符来创建类的实例,但是构造函数上的方法和属性在每个示例上都存在,不能共享,于是我们引入原型来实现方法和属性的共享。

一些常用的JavaScript 知識點整理

原型

最后,我们将需要共享的方法和属性定义在原型上,把专属于实例的方法和属性放到构造函数中。到这儿,我们就通过构造函数+原型的方式定义了一个类。

// 构造函数 function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"];

} // 原型 Person.prototype = { constructor: Person,
    sayName: function() { return this.name;
    }
} // 实例化 var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor");

person1.friends.push("Van");
alert(person1.friends); //输出"Shelby,Count,Van" alert(person2.friends); //输出"Shelby,Count" alert(person1.friends === person2.friends); //输出false alert(person1.sayName === person2.sayName); //输出true

实现继承

前文讲了如何定义一个类,那么我们定义一个父类,一个子类。

如何让子类继承父类呢?不扯别的,直接告诉你。JavaScript通过原型链来实现继承!

如何构建原型链呢?将子类实例赋值给父类构造函数的原型即可。好绕,但是千万得记住了!

一些常用的JavaScript 知識點整理

原型链继承

构建原型链之后,子类就可以访问父类的所有属性和方法!

// 父类 function SuperType() { this.property = true;
}
SuperType.prototype.getSuperValue = function() { return this.property;
}; // 子类 function SubType() { this.subproperty = false;
} //子类继承父类 SubType.prototype = new SuperType(); //给子类添加新方法 SubType.prototype.getSubValue = function() { return this.subproperty;
}; //重写父类的方法 SubType.prototype.getSuperValue = function() { return false;
}; // 实例化 var instance = new SubType(); console.log(instance.getSuperValue()); //输出false

面向对象的知识可以用一本书来写,这儿只是简单的介绍下最基础最常用的概念。

函数表达式

JavaScript中有两种定义函数的方式:函数声明和函数表达式。

使用函数表达式无须对函数命名,从而实现动态编程,也即匿名函数。有了匿名函数,JavaScript函数有了更强大的用处。

递归

递归是一种很常见的算法,经典例子就是斐波拉契数列。也不扯其他的,直接说递归的最佳实践,上代码:

// 最佳实践,函数表达式 var factorial = (function f(num) { if (num <= 1) { return 1;
    } else { return num * f(num - 1);
    }
}); // 缺点: // factorial存在被修改的可能 // 导致 return num * factorial(num - 1) 报错 function factorial(num) { if (num <= 1) { return 1;
    } else { return num * factorial(num - 1);
    }
} // 缺点: // arguments.callee,规范已经不推荐使用 function factorial(num) { if (num <= 1) { return 1;
    } else { return num * arguments.callee(num - 1);
    }
}

递归就是这样,好多人还在使用arguments.callee的方式,改回函数表达式的方式吧,这才是最佳实践。

啰嗦一句,好多人觉得递归难写,其实你将其分为两个步骤就会清晰很多了。

✦ 边界条件,通常是if-else。

✦ 递归调用。

按这个模式,找几个经典的递归练练手,就熟悉了。

闭包

很多人经常觉得闭包很复杂,很容易掉到坑里,其实不然。

那么闭包是什么呢?如果一个函数可以访问另一个函数作用域中的变量,那么前者就是闭包。自然,创建闭包的常用方式就是在一个函数内部创建另一个函数!

并没有什么神奇的,这就是闭包,闭包就是一个理所当然的现象,也就是在父函数中定义子函数,然后子函数可以访问父函数的作用域。

我们通常是因为被闭包坑了,才会被闭包吓到,尤其是面试题里一堆闭包。

闭包的定义前面提了,如何创建闭包也说了,那么我们说说闭包的缺陷以及如何解决?

/* 我们通过subFuncs返回函数数组,然后分别调用执行 */ // 返回函数的数组subFuncs,而这些函数对superFunc的变量有引用 // 这就是一个典型的闭包 // 那么有什么问题呢? // 当我们回头执行subFuncs中的函数的时候,我们得到的i其实一直都是10,为什么? // 因为当我们返回subFuncs之后,superFunc中的i=10 // 所以当执行subFuncs中的函数的时候,输出i都为10。 //  // 以上,就是闭包最大的坑,一句话理解就是: // 子函数对父函数变量的引用,是父函数运行结束之后的变量的状态 function superFunc() { var subFuncs = new Array(); for (var i = 0; i < 10; i++) {
        subFuncs[i] = function() { return i;
        };
    } return subFuncs;
} // 那么,如何解决上诉的闭包坑呢? // 其实原理很简单,既然闭包坑的本质是:子函数对父函数变量的引用,是父函数运行结束之后的变量的状态 // 那么我们解决这个问题的方式就是:子函数对父函数变量的引用,使用运行时的状态 // 如何做呢? // 在函数表达式的基础上,加上自执行即可。 function superFunc() { var subFuncs = new Array(); for (var i = 0; i < 10; i++) {
        subFuncs[i] = function(num) { return function() { return num;
            };
        }(i);
    } return subFuncs;
}

综上,闭包本身不是什么复杂的机制,就是子函数可以访问父函数的作用域。

而由于JavaScript函数的特殊性,我们可以返回函数,如果我们将作为闭包的函数返回,那么该函数引用的父函数变量是父函数运行结束之后的状态,而不是运行时的状态,这便是闭包最大的坑。而为了解决这个坑,我们常用的方式就是让函数表达式自执行。

此外,由于闭包引用了祖先函数的作用域,所以滥用闭包会有内存问题。

好像把闭包说得一无是处,那么闭包有什么用处呢?

主要是封装吧...

封装

闭包可以封装私有变量或者封装块级作用域。

➙ 封装块级作用域

JavaScript并没有块级作用域的概念,只有全局作用域和函数作用域,那么如果想要创建块级作用域的话,我们可以通过闭包来模拟。

创建并立即调用一个函数,就可以封装一个块级作用域。该函数可以立即执行其中的代码,内部变量执行结束就会被立即销毁。

function outputNumbers(count) { // 在函数作用域下,利用闭包封装块级作用域 // 这样的话,i在外部不可用,便有了类似块级作用域 (function() { for (var i = 0; i < count; i++) {
            alert(i);
        }
    })();

    alert(i); //导致一个错误!  } // 在全局作用域下,利用闭包封装块级作用域 // 这样的话,代码块不会对全局作用域造成污染 (function() { var now = new Date(); if (now.getMonth() == 0 && now.getDate() == 1) {
        alert("Happy new year!");
    }
})(); // 是的,封装块级作用域的核心就是这个:函数表达式 + 自执行! (function() { //这里是块级作用域 })();

➙ 封装私有变量

JavaScript也没有私有变量的概念,我们也可以使用闭包来实现公有方法,通过隐藏变量暴露方法的方式来实现封装私有变量。

(function() { //私有变量和私有函数 var privateVariable = 10; function privateFunction() { return false;
    } //构造函数 MyObject = function() {}; //公有/特权方法 MyObject.prototype.publicMethod = function() {
        privateVariable++; return privateFunction();
    };
})();

总结说点啥?

这差不多就是JavaScript的一些基础语法和稍微高级一些的用法,其实所谓的高级,都是JavaScript“不太成熟”的表现,尤其是面向对象,出于工程化的需要但是JavaScript本身并不完美支持。好在ES6最新标准解决了很多问题,结合Babel用起来也不用太考虑兼容性问题,如果你是新手的话,建议你直接去撸ES6+Babel吧。

✦ JavaScript的基础主要包括:5中基本数据类型、1种复杂的数据类型、操作符、控制语句、函数等。

✦ 了解基本的语法后,你还需要学习学习JavaScript的变量、作用域、作用域链。

✦ 常见的引用类型可以边查边用。作为过来人,建议多学学正则,对你的代码功底会有较大的提升。

✦ 面向对象编程的部分外面有很多种方式,你只需要记住使用构造函数+原型去定义一个类,使用原型链去实现继承即可。更多的扩展,去翻翻书吧。

✦ 函数表达式引出了几个比较好玩的东西:递归、闭包、封装。记住递归的最佳实践、闭包的定义及缺陷、闭包的适用场景。

JavaScript作为一门动态语言,和其他语言有较大的差异,这也造成很多人学习JavaScript时会觉得难学。但你现在看看前文,虽然是一个简略的总结,但JavaScript主要的内容就这些了,所以不要被自己吓到了。


以上是一些常用的JavaScript 知識點整理的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
es6数组怎么去掉重复并且重新排序es6数组怎么去掉重复并且重新排序May 05, 2022 pm 07:08 PM

去掉重复并排序的方法:1、使用“Array.from(new Set(arr))”或者“[…new Set(arr)]”语句,去掉数组中的重复元素,返回去重后的新数组;2、利用sort()对去重数组进行排序,语法“去重数组.sort()”。

JavaScript的Symbol类型、隐藏属性及全局注册表详解JavaScript的Symbol类型、隐藏属性及全局注册表详解Jun 02, 2022 am 11:50 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于Symbol类型、隐藏属性及全局注册表的相关问题,包括了Symbol类型的描述、Symbol不会隐式转字符串等问题,下面一起来看一下,希望对大家有帮助。

原来利用纯CSS也能实现文字轮播与图片轮播!原来利用纯CSS也能实现文字轮播与图片轮播!Jun 10, 2022 pm 01:00 PM

怎么制作文字轮播与图片轮播?大家第一想到的是不是利用js,其实利用纯CSS也能实现文字轮播与图片轮播,下面来看看实现方法,希望对大家有所帮助!

JavaScript对象的构造函数和new操作符(实例详解)JavaScript对象的构造函数和new操作符(实例详解)May 10, 2022 pm 06:16 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于对象的构造函数和new操作符,构造函数是所有对象的成员方法中,最早被调用的那个,下面一起来看一下吧,希望对大家有帮助。

JavaScript面向对象详细解析之属性描述符JavaScript面向对象详细解析之属性描述符May 27, 2022 pm 05:29 PM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于面向对象的相关问题,包括了属性描述符、数据描述符、存取描述符等等内容,下面一起来看一下,希望对大家有帮助。

javascript怎么移除元素点击事件javascript怎么移除元素点击事件Apr 11, 2022 pm 04:51 PM

方法:1、利用“点击元素对象.unbind("click");”方法,该方法可以移除被选元素的事件处理程序;2、利用“点击元素对象.off("click");”方法,该方法可以移除通过on()方法添加的事件处理程序。

整理总结JavaScript常见的BOM操作整理总结JavaScript常见的BOM操作Jun 01, 2022 am 11:43 AM

本篇文章给大家带来了关于JavaScript的相关知识,其中主要介绍了关于BOM操作的相关问题,包括了window对象的常见事件、JavaScript执行机制等等相关内容,下面一起来看一下,希望对大家有帮助。

foreach是es6里的吗foreach是es6里的吗May 05, 2022 pm 05:59 PM

foreach不是es6的方法。foreach是es3中一个遍历数组的方法,可以调用数组的每个元素,并将元素传给回调函数进行处理,语法“array.forEach(function(当前元素,索引,数组){...})”;该方法不处理空数组。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

WebStorm Mac版

WebStorm Mac版

好用的JavaScript開發工具

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用