写给前端初学者:JavaScipt初学入门的一些小疑问
Posted 我是真的不会前端
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了写给前端初学者:JavaScipt初学入门的一些小疑问相关的知识,希望对你有一定的参考价值。
作为一名前端开发者或者说是即将进这个门的学生。js是永远离不开的东西。或者说,几乎是每个前端CV工程师的饭碗。
首先,这是个什么玩意:
他是种什么语言,他跟那个流水的编程语言,铁打的java有什么关系
java跟javascript的关系 就跟周杰伦跟周杰的关系一样,就是…没有关系。
但你说完全没有关系吧也不准确。当初网景公司开发javascript。就是蹭了一手java当年的热度。就跟王一博很火。我取个名字叫王二博。反正不违法不违规。至少我在公司这名字能起到作用。其次是,但凡是本科或者说事是计算机科班出身或者是有过开发经历敲过代码的。在接触过js之后。你会发现,这玩意又像C,又像C++,又像java。包括一些概念。什么类,继承,静态等等。是不是xdm又看到了JAVA的影子。别急。这个似像四不像的玩意。却贯穿了每个前端程序员前端开发生涯的一生,也就是说。没有人能跑的掉被JS折磨的时候。
但是吧,前端又是幸运的,相比后端语言的多样化,前端的一切都是围绕js开始的。而且就是也可以写后端。比如node.js
这玩意 学久了上头,讲真。就当你带着你女朋友出去玩得时候(假设真实存在,没有你可以new一个)。当你对象突然说哇好好看。你会突然眉头一紧。var?var啥。用let不行嘛
好了开完玩笑后。来谈谈真正贯穿js始终的几个特性:
万物皆对象?
首先,对象在JS中长这样
属性加方法。打开proto属性。好巧不巧,依然是个对象。
同时,我们所学到的任何。数组,字符串,你所能看到的所有节点,所有样式。他都都都可以是对象。所以在js中,对象才是yyds。但现在,请开始冷静下来。真就如此嘛。
不管是看视频还是培训机构还是学校教的学过点的都知道,js中有七大数据类型。前六种为基本数据类型,Object 为引用类型(对象类型),值得注意一点的是用 typeof null 会返回 Object,这实际上是一个bug,Null 实际上是基本类型的值。引用数据类型:object
使用typeof检查数据类型 可以知道 typeof(null)返回的是object。
这是由于计算机存储造成的。到时候你可以用instance of 来查复杂数据类型。其实吧,
在底层存储对象时都是二进制,JavaScript中如果二进制前三位都是0就会被判断为object类型,
null的二进制表示全是0,所以返回的是“object”。所谓对象,都有自己的属性和方法。理论上都可以操作对象的属性,进行增删改查。函数是可以直接当成对象使用的。
而原始数据类型存储在栈中 他们的存储结构是不能改变的,改变的可以是地址。
var str = "hello world";
str = 123;
console.log(str)
打印出来肯定是123。 因为str的存住地址发生了改变。
引用数据类型 是存储在堆和栈中 但对象里面去增加属性和方法是不会改变存储的地址的。
如果给原始类型添加属性 str.age = 18; 不会报错,但在系统检查为原始数据类型的瞬间会被删除。
typeof null // object 原理:不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判 断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。
根据 JavaScript 对语言类型的分类,很容易知道,并不是 JavaScript 万物皆对象,或者说任何非基本类型的都是对象类型。所以javascript中一切皆对象,确切说应该是一切引用类型都是对象;反正你到时候不管面试吹逼还是跟你的学弟学妹欢乐装杯。这么说,一定不会错。
2.函数是一等公民?
一等公民这个名字听起来很高大上,但是也相当晦涩,这个与翻译也没什么关系,因为first class citizen。说实话,这种稀奇古怪的理解你说跟翻译没关系吧,我是不信。这我读初中的侄子叫他翻译也是翻译一等公民嘛。
JavaScript函数是一等公民,是什么意思呢?先引用隔壁简书一位大佬的一段话。
n general, a value in a programming language is said to have first-class status if it can be passed as a parameter, returned from a subroutine, or assigned into a variable.一等公民可以作为函数参数,可以作为函数返回值,也可以赋值给变量。例如,字符串在几乎所有编程语言中都是一等公民,字符串可以做为函数参数,字符串可以作为函数返回值,字符串也可以赋值给变量。
对于各种编程语言来说,函数就不一定是一等公民了,比如Java 8之前的版本。
对于JavaScript来说,函数可以赋值给变量,也可以作为函数参数,还可以作为函数返回值,因此JavaScript中函数是一等公民。他可以作为参数,也可以将函数给变量赋值。还可以做返回值。也就是说,函数为第一公民是函数式编程的必要条件。higher-order functions,即高阶函数,就是使用函数作为参数的函数,它在函数式编程中很常见。
3.typeof NaN == “number”?
NAN是js中一个可能正常逻辑中感觉略离谱的一个特殊数值类型。NaN 是一种特殊的 number 类型,所以 typeof 之后求得的是 number 类型。
NaN 的意思是说明这个值不是数字,例如我们在把字母转换成整数或者浮点数时,他返回的值就是 NaN。NaN 与任何值都不相等,与他自己也不相等
所以在判断某个值不是数字的时候不能使用==NaN,这样的话无论他是不是数字都返回 false ,这里应该使用isNaN()函数来判断他是否是 NaN 值
另外附上其他类型的 typeof 返回值
undefined:undefined
null:object
string:string
number:number
boolean:boolean
function:function
object:object
4.js中的class只是语法糖?
在 ES6 规范中,引入了 class 的概念。使得 JS 开发者终于告别了,直接使用原型对象模仿面向对象中的类和类继承时代。至少看起来的面向对象,像模像样了。但是JS 中并没有一个真正的 class 原始类型
class通过类来创建对象,使得开发者不必写重复的代码,以达到代码复用的目的。它基于的逻辑是,两个或多个对象的结构功能类似,可以抽象出一个模板,依照模板复制出多个相似的对象。就像自行车制造商一遍一遍地复用相同的蓝图来制造大量的自行车。
class Person {
constructor(name){
this.name = name
}
hello(){
console.log('Hello, my name is ' + this.name + '.');
}
}
var aaa = new Person('aaa');
xiaoMing.hello() // Hello, my name is aaa.
aaa 是通过类 Person 实例化出来的对象。对象 aaa是按照类 Person 这个模板,实例化出来的对象。实例化出来的对象拥有类预先订制好的结构和功能。
使用 class 的语法,让开发者告别了使用 prototype 模仿面向对象的时代。但是,class 并不是 ES6 引入的全新概念,但它的原理依旧是原型继承。或者说直白了点。变得跟隔壁敲java的大哥更像了那么点。
而且,其实class是function类型
class Person {
}
typeof Person // function
通过类型判断,我们可以得知,class 的并不是什么全新的数据类型,它实际只是 function (或者说 object)。那他到底是不是语法糖,其实每个人各有自己的看法。反正我作为高级CV带师,能造轮子就行了。
5. _proto _ 和prototype的区别是啥
prototype 属性,它指向一个特殊性对象:原型对象。
型对象所以特殊,是因为它拥有一个普通对象没有的能力:将它的属性共享给其他对象。
那 原型对象是如何将它的属性分享给其他对象的呢?
function Person() {
this.name = name
}
// 1. 首先给 Person.prototype 原型对象添加了相应方法 。
Person.prototype.describe = function(){
console.log('Hello, my name is ' + this.name + '.');
}
// 2. 实例化对象的 __proto__ 指向 Person.prototype
var jane = new Person('jane');
jane.__proto__ === Person.prototype;
// 3. 读取 describe 方法时,实际会沿着原型链查找到 Person.prototype 原型对象上。
jane.describe() // Hello, my name is jane.
首先给 Person.prototype 属性所指的原型对象上添加了一个方法 describe。
在使用 new 关键字创建对象时,会默认给该对象添加一个原型属性 proto,该属性指向 Person.prototype 原型对象。
在读取 describe 方法时,首先会在 jane 对象查找该方法,但是 jane 对象并不直接拥有 describe 方法。所以会沿着原型链查找到 Person.prototype 原型对象上,最后返回该原型对象的 describe 方法。
JS 中面向对象实例化的背后原理,实际上就是 原型对象
你要没钱了,默认想赵家人要钱,你找你爸要5毛钱,买个辣条
构造函数声明就会给一个原型对象
2 构造函数通过prototype访问原型对象.
3 实例对象可以直接访问原型对象的方法和属性.
理解上述原理后,还需要注意 prototype 与 proto 属性的区别。
proto 所指的对象,真正将它的属性分享给它所属的对象。所有的对象都有 proto 属性,它是一个内置属性,被用于继承。
prototype 是一个只属于 function 的属性。当使用 new 方法调用该构造函数的时候,它被用于构建新对象的 proto。另外它不可写,不可枚举,不可配置。
( new Foo() ).__proto__ === Foo.prototype
( new Foo() ).prototype === undefined
6.动态获取和静态获取有什么区别?
其实这里非常容易翻车,因为对于动态创建的节点。不同的获取方式可能或导致不同的结果。甚至直接报错。
静态获取方法
document.getElementById
obj.querySelector
obj.querySelectorAll
动态获取方法(每次使用时候会回去重新获取一次)
obj.getElementsByClassName
obj.getElementsByTagName
document.getElementsByName
可以简单理解为静态获取只会在调用静态获取方法的地方获取一次结果,以后使用时就使用这次获取的结果,所以每次的结果都是相同的;
而动态获取则会在使用到的地方每次都重新调用动态获取方法,报以每次的结果可能不同;
//静态获取
var op = document.querySelectorAll("p");
var b = document.createElement("p");
box.appendChild(b);
//op的长度是1
alert(op.length);
//动态获取 每次使用会回去重新获取一次
var op = document.getElementsByTagName("p");
var b = document.createElement("p");
box.appendChild(b);
//op的长度是2
alert(op.length)
回调函数有什么用?
回调函数就是在执行了一个东西了之后,你可以有一个东西实现你想用执行的返回结果干些什么事情的东西,或者说是在执行完当前的东西你还想继续干些什么的一个参数;
回调函数的英文解释为:A callback is a function that is passed as an argument to another function and is executed after its parent function has completed.
翻译一下就是:
翻译过来就是:回调函数是一个作为变量传递给另外一个函数的函数,它在主体函数执行完之后执行。
function A有一个参数function B,function B会在function A执行完成之后被调用执行。
字面上的理解:
回调函数就是一个参数,将这个函数作为参数传到另一个函数里面,当那个函数执行完之后,再执行传进去的这个函数。这个过程就叫做回调。
回调,回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数 。
回调函数的使用方法
function a(callbackFunction){
alert("这是parent函数a");
var m =1;
var n=3;
return callbackFunction(m,n);
}
function b(m,n){
alert("这是回调函数B");
return m+n;
}
$(function(){
var result = a(b);
alert("result = "+ result);
});
// 执行顺序为:
这是parent函数a
这是回调函数B
result = 4
函数首先执行了主题函数a,之后调用了回调函数b,最后返回函数a的返回值。
以上是关于写给前端初学者:JavaScipt初学入门的一些小疑问的主要内容,如果未能解决你的问题,请参考以下文章