2018-6-28復(fù)習(xí)
每一次回頭看基礎(chǔ)僚匆,都有新的理解
Function.prototype.call
函數(shù)實(shí)例的call方法,可以指定函數(shù)內(nèi)部this的指向(即:函數(shù)執(zhí)行時(shí)所在的作用域,--- 函數(shù)運(yùn)行時(shí)所在的對(duì)象 )
口柳,然后在所指定的作用域中,調(diào)用該函數(shù)。
注意: call方法是函數(shù)的方法
應(yīng)用:
- 將 ( 類似數(shù)組的對(duì)象 ) 轉(zhuǎn)換成 ( 數(shù)組 )
(1)
[].slice.call(arguments)
等于 Array.prototype.slice.call(arguments)
等于 Array.from(arguments)
--- [].slice.call(arguments, x,y)參數(shù)x,y是slice()方法執(zhí)行時(shí)傳入的參數(shù)
(2)
slice()方法 ----- 截取數(shù)組的一部分役听,返回截取部分的新數(shù)組,不改變?cè)瓟?shù)組
slice(start, end)方法甜滨,截取數(shù)組的一部分衣摩,start是啟始位置捂敌,end是終止位置(不包含)
數(shù)組的slice()方法不加參數(shù)時(shí),等于數(shù)組的拷貝
實(shí)例:
Array.prototype.slice.call({ 0: 'a', 1: 'b', length: 2 }) // ['a', 'b']
--- 將slice()方法中的this綁定在參數(shù)對(duì)象上栏渺,并在參數(shù)對(duì)象的作用域內(nèi)執(zhí)行slice()方法
函數(shù)實(shí)例的call方法锐涯,可以指定函數(shù)內(nèi)部this的指向(即:函數(shù)執(zhí)行時(shí)所在的作用域磕诊,--- 函數(shù)運(yùn)行時(shí)所在的對(duì)象 )
,然后在所指定的作用域中纹腌,調(diào)用該函數(shù)霎终。
- 函數(shù)實(shí)例的call方法,可以指定函數(shù)內(nèi)部this的指向升薯,指定函數(shù)運(yùn)行時(shí)所在的對(duì)象莱褒,然后在指定的作用域中,執(zhí)行該函數(shù)涎劈。
- call方法會(huì)執(zhí)行函數(shù)广凸,無需手動(dòng)調(diào)用
- call方法的參數(shù)是一個(gè)對(duì)象阅茶,如果參數(shù)是空,null谅海,undefined脸哀,則默認(rèn)傳入全局對(duì)象window
- call方法可以接受多個(gè)參數(shù) :
第一個(gè)參數(shù)是this所要指向的對(duì)象。
后面的參數(shù)是函數(shù)調(diào)用時(shí)扭吁,所需的參數(shù)
var obj = {};
var f = function () {
return this;
};
f() === window // true
f.call(obj) === obj // true
--- 把f函數(shù)的this綁定在obj對(duì)象上撞蜂,并在obj的作用域中,執(zhí)行f函數(shù)
var n = 123;
var obj = { n: 456 };
function a() {
console.log(this.n);
}
a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456
--- 參數(shù)是null侥袜,空蝌诡,undefined時(shí)送漠,默認(rèn)傳入的是全局對(duì)象 window
Function.prototype.apply()
apply方法的作用與call方法類似闽寡,也是改變this指向,然后再調(diào)用該函數(shù)涎永。唯一的區(qū)別就是,它接收一個(gè)數(shù)組作為函數(shù)執(zhí)行時(shí)的參數(shù)
- apply()方法也是改變方法中this的執(zhí)行妈倔,和call()相同
- apply() 與 call() 方法不同的是,apply接收的參數(shù)是一個(gè)數(shù)組
- apply()當(dāng)?shù)谝粋€(gè)參數(shù)是null捧挺,空闽烙,undefined時(shí)捕发,默認(rèn)傳入的是全局對(duì)象window
func.apply(ojb, [arg1, arg2, ...])
apply()方法:
第一個(gè)參數(shù)充石,是this所要綁定的對(duì)象拉岁,this所要指向的對(duì)象
第二個(gè)參數(shù)是一個(gè)數(shù)組喊暖,會(huì)將成員依次作為函數(shù)調(diào)用時(shí)的參數(shù)
function f(x, y){
console.log(x + y);
}
f.call(null, 1, 1) // 2
f.apply(null, [1, 1]) // 2
解析:
f()函數(shù),本來是接受兩個(gè)參數(shù)巩掺,但在使用apply方法后,就可以變成独令,接受一個(gè)數(shù)組為參數(shù)
應(yīng)用:
- 找出數(shù)組中最大的數(shù)---(或者最小的數(shù))
Math.max(1,2,5,3) // 5
Math.min(1,2,3) // 1
const arr = [1,6,2,3,4,5];
Math.max.apply(null, arr) // 6 將max方法中的this指向頂層對(duì)象,參數(shù)是arr數(shù)組
等于:Math.max.apply(undefined, arr)
等于:Math.max([...arr])
- 將數(shù)組的 ( 空元素 ) 變成 ( undefined )
- 通過apply方法遍膜,利用Array構(gòu)造函數(shù)將數(shù)組的空元素變成undefined。
空元素與undefined的差別在于挽懦,數(shù)組的forEach方法會(huì)跳過空元素冀偶,但是不會(huì)跳過undefined。因此客年,遍歷內(nèi)部元素的時(shí)候量瓜,會(huì)得到不同的結(jié)果。
Array.apply(null, ['a', ,'b'])
等于: [...['a', , 'b']]
// [ 'a', undefined, 'b' ]
- 轉(zhuǎn)換類似數(shù)組的對(duì)象
- 現(xiàn)在有了展開運(yùn)算符,apply方法的各種運(yùn)用都可以用展開運(yùn)算符或者其他es6語法代替
Function.prototype.bind()
bind方法用于將函數(shù)體內(nèi)的this綁定到某個(gè)對(duì)象杠纵,然后返回一個(gè)新函數(shù)。
-
bind方法
不主動(dòng)執(zhí)行函數(shù) -
call方法
和apply方法
都在綁定函數(shù)this指向的對(duì)象后韩容,在指向?qū)ο蟮淖饔糜騼?nèi)主動(dòng)執(zhí)行該函數(shù) - bind方法的參數(shù),就是所要綁定的this對(duì)象
- bind可以接收多個(gè)參數(shù)请梢,第一個(gè)參數(shù)是要綁定的this的對(duì)象,其他參數(shù)是原函數(shù)的參數(shù)
- 如果bind方法的第一個(gè)參數(shù)是null或undefined够坐,等于將this綁定到全局對(duì)象梯影,函數(shù)運(yùn)行時(shí)this指向頂層對(duì)象(瀏覽器為window)
var counter = {
count: 0,
inc: function () {
this.count++;
}
};
var func = counter.inc.bind(counter);
func();
counter.count // 1
解析:
1.
將counter.inc方法中的this綁定在counter對(duì)象上
如果不綁定,var func = counter.inc將該方法賦值給變量后感猛,this指向了頂層對(duì)象window
var add = function (x, y) {
return x * this.m + y * this.n;
}
var obj = {
m: 2,
n: 2
};
var newAdd = add.bind(obj, 5); // add函數(shù)的第一個(gè)參數(shù)
newAdd(5) // 20 // add函數(shù)的第二個(gè)參數(shù)
bind函數(shù)注意點(diǎn)
- bind方法每運(yùn)行一次戳寸,就返回一個(gè)新函數(shù)疫鹊。
- 結(jié)合回調(diào)函數(shù)使用 -------------( 重要 )
回調(diào)函數(shù)是 JavaScript 最常用的模式之一聋迎,但是一個(gè)常見的錯(cuò)誤是,將包含this的方法直接當(dāng)作回調(diào)函數(shù)牺堰。解決方法就是使用bind方法,將counter.inc綁定counter筏养。
- 不能將含有this的方法直接當(dāng)做回調(diào)函數(shù)。而應(yīng)該用bind方法茎辐,將this綁定給原對(duì)象上
var counter = {
count: 0,
inc: function () {
'use strict';
this.count++;
}
};
function callIt(callback) {
callback();
}
callIt(counter.inc.bind(counter));
counter.count // 1
構(gòu)造函數(shù)的缺點(diǎn)
同一個(gè)構(gòu)造函數(shù)的多個(gè)實(shí)例之間废膘,無法共享屬性,從而造成對(duì)系統(tǒng)資源的浪費(fèi)灌闺。
-
構(gòu)造函數(shù)內(nèi)部,通過this定義的屬性,在使用new命令生成實(shí)例對(duì)象的時(shí)候宅此,這些屬性會(huì)定義在實(shí)例對(duì)象上,即 hasOwnProperty 為 true
---------- ( 重要 )
function Cat(name, color) {
this.name = name;
this.color = color;
this.meow = function () {
console.log('喵喵');
};
}
var cat1 = new Cat('大毛', '白色');
var cat2 = new Cat('二毛', '黑色');
cat1.meow === cat2.meow --- 不相等,函數(shù)是引用類型的數(shù)據(jù)枝嘶,說明無法共享屬性
// false
obj.hasOwnProperty(prop) --- 表示:prop是否是obj的自身屬性,不含繼承屬性
cat1.hasOwnProperty('name'); // true
總結(jié):
1. 構(gòu)造函數(shù)內(nèi)部定義的屬性穷当,在生成實(shí)例對(duì)象的時(shí)候,會(huì)成為實(shí)例對(duì)象自身的屬性汪疮。
2. 構(gòu)造函數(shù)各個(gè)實(shí)例之間無法共享屬性卖丸,造成系統(tǒng)資源浪費(fèi)
3. 解決辦法是 原型對(duì)象
prototype原型對(duì)象
原型對(duì)象的所有屬性和方法,都能被實(shí)例對(duì)象所共享。
- 也就是說弦撩,如果屬性和方法定義在原型對(duì)象上,那么所有實(shí)例對(duì)象就能共享這些屬性和方法
構(gòu)造函數(shù)生成的實(shí)例之間無法共享構(gòu)造函數(shù)的屬性和方法偏形,因?yàn)檫@些屬性和方法是生成在實(shí)例上的
- 對(duì)于構(gòu)造函數(shù)來說队橙,prototype屬性會(huì)在生成實(shí)例對(duì)象的時(shí)候,成為實(shí)例對(duì)象的原型對(duì)象(那么原型對(duì)象的屬性和方法就能被實(shí)例對(duì)象所共享)
- 原型對(duì)象的屬性贮匕,不是實(shí)例對(duì)象自身的屬性。修改原型對(duì)象敦锌,變動(dòng)就立刻體現(xiàn)在所有實(shí)例對(duì)象上
- 當(dāng)實(shí)例對(duì)象本身沒有某個(gè)屬性和方法時(shí),會(huì)在原型對(duì)象上尋找該屬性和方法腥刹,沒找到,在去原型的原型上找录别。直到Object.prototype上都沒找到朽色,就返回undefined
總結(jié):
原型對(duì)象的作用就是定義: 所有實(shí)例對(duì)象所共享的屬性和方法
function Animal(name) {
this.name = name;
}
Animal.prototype.color = 'white';
// 構(gòu)造函數(shù)的prototype屬性在生成實(shí)例對(duì)象時(shí),會(huì)成為實(shí)例的原型對(duì)象
// prototype對(duì)象上的color屬性组题,會(huì)被實(shí)例共享
var cat1 = new Animal('大毛');
var cat2 = new Animal('二毛');
cat1.color // 'white'
cat2.color // 'white'
原型鏈
所有對(duì)象都有自己原型對(duì)象
- 所有對(duì)象都繼承了
Object.prototype對(duì)象
的屬性和方法葫男,這就是所有對(duì)象都具有valueOf
方法 和toString
方法的原因,都繼承自O(shè)bject.prototype對(duì)象 -
Object.prototype
的原型是null
崔列, null沒有任何屬性和方法,也沒有自己的原型边翼,原型鏈到此終結(jié)江滨,原型鏈的盡頭是null镊屎。 - Object.getPrototypeOf() 返回參數(shù)對(duì)象的原型對(duì)象 --------( 重要 )
- 如果自身和原型上都定義了同名的屬性,則優(yōu)先讀取自身屬性。'overriding'
Object.getPrototypeOf(Object.prototype)
Object.getPrototypeOf() --- 返回參數(shù)對(duì)象的原型對(duì)象
// null
// 表示Object.prototype對(duì)象的原型對(duì)象是null
var MyArray = function () {};
MyArray.prototype = new Array();
MyArray.prototype.constructor = MyArray;
var mine = new MyArray();
mine.push(1, 2, 3);
mine.length // 3
mine instanceof Array // true
解析:
1. mine 是構(gòu)造函數(shù)MyArray 生成實(shí)例對(duì)象
2. 構(gòu)造函數(shù)的 MyArray.prototype對(duì)象成為實(shí)例對(duì)象的原型對(duì)象
3. MyArray.prototype指向了數(shù)組實(shí)例,那么MyArray的實(shí)例就具有 數(shù)組的屬性和方法
4. 所有mine具有數(shù)組的屬性和方法
5. instanceof運(yùn)算符 左邊是實(shí)例 右邊是構(gòu)造函數(shù) 返回布爾值
constructor屬性
prototype
對(duì)象有一個(gè)constructor
屬性桶蛔,默認(rèn)指向 prototype對(duì)象所在的構(gòu)造函數(shù)斩郎。---------------------------------------------------- ( 重要 )
- constructor屬性定義在prototype對(duì)象上姻蚓,就意味著可以被所有實(shí)例所繼承
(prototype對(duì)象是實(shí)例對(duì)象的原型對(duì)象, 實(shí)例對(duì)象繼承原型對(duì)象的屬性和方法)
- constructor屬性的作用,用來確定實(shí)例對(duì)象由哪個(gè)構(gòu)造函數(shù)生成
- 利用constructor屬性可以從一個(gè)實(shí)例對(duì)象新建另一個(gè)實(shí)例對(duì)象
constructor屬性表示原型對(duì)象與構(gòu)造函數(shù)之間的關(guān)聯(lián)關(guān)系扑浸,如果修改了原型對(duì)象,一般會(huì)同時(shí)修改constructor屬性桥言,防止引用的時(shí)候出錯(cuò)枯夜。
( 重要 )
function P() {}
P.prototype.constructor === P // true
解析:
1. P構(gòu)造函數(shù)(首字母大寫)的prototype屬性是一個(gè)對(duì)象
2. prototype對(duì)象的constructor屬性指向prototype對(duì)象所在的構(gòu)造函數(shù)
3. P.prototype.constructor === P 布爾值就是true
( 重要 )
function P() {}
var p = new P();
p.constructor === P // true
p.constructor === P.prototype.constructor // true
p.hasOwnProperty('constructor') // false 是繼承的,不是自身的屬性
解析:
1. prototype對(duì)象的constructor屬性,指向prototype對(duì)象所在構(gòu)造函數(shù)
2. constructor是實(shí)例對(duì)象的原型對(duì)象的屬性楞遏,會(huì)被實(shí)例所繼承
所以
實(shí)例p繼承了constructor屬性沧奴,p.constructor = P = P.prototype.constructor
利用constructor屬性灶芝,可以從一個(gè)實(shí)例生成另一個(gè)實(shí)例
因?yàn)? constructor屬性指向的就是構(gòu)造函數(shù)
function Constr() {}
var x = new Constr();
var y = new x.constructor(); //注意x.constructor === Constr,這里要執(zhí)行
// x.constructor間接調(diào)用構(gòu)造函數(shù)
y instanceof Constr // true
- constructor屬性表示原型對(duì)象與構(gòu)造函數(shù)之間的關(guān)聯(lián)關(guān)系蜘腌,如果修改了原型對(duì)象养泡,一般會(huì)同時(shí)修改constructor屬性惩妇,防止引用的時(shí)候出錯(cuò)路召。
( 重要 )
function Person(name) {
this.name = name;
}
Person.prototype.constructor === Person // true
Person.prototype = {
method: function () {}
};
Person.prototype.constructor === Person // false
Person.prototype.constructor === Object // true
解析:
1. Person.prototype 修改成了對(duì)象
2. 構(gòu)造函數(shù)Person的原型對(duì)象改了,但沒改constructor屬性馍乙,導(dǎo)致這個(gè)屬性不再指向Person
3. 對(duì)象的構(gòu)造函數(shù)是Object構(gòu)造函數(shù)
4. 所以修改原型對(duì)象時(shí)丝格,一般要同時(shí)修改constructor屬性的指向
instanceof運(yùn)算符
instanceof運(yùn)算符返回一個(gè)布爾值撑瞧,表示對(duì)象是否為某個(gè)構(gòu)造函數(shù)的實(shí)例。
- instanceof運(yùn)算符返回的是boolean值
- 表示 ( 對(duì)象 ) 是否是 ( 構(gòu)造函數(shù) ) 的 ( 實(shí)例 )
- instance:是實(shí)例的意思
- ( instanceof ) 運(yùn)算符 ( 左邊是實(shí)例對(duì)象 )显蝌,( 右邊是構(gòu)造函數(shù) )季蚂。
- 它會(huì)檢查右邊構(gòu)造函數(shù)的原型對(duì)象prototype, 是否在左邊對(duì)象的原型鏈上。
由于instanceof檢查整個(gè)原型鏈琅束,因此同一個(gè)實(shí)例對(duì)象扭屁,可能會(huì)對(duì)多個(gè)構(gòu)造函數(shù)都返回true。
- instanceof的原理是檢查右邊構(gòu)造函數(shù)的prototype屬性涩禀,是否在左邊對(duì)象的原型鏈上料滥。
- 有一種特殊情況,就是左邊對(duì)象的原型鏈上艾船,只有null對(duì)象葵腹。這時(shí),instanceof判斷會(huì)失真屿岂。
- instanceof運(yùn)算符的一個(gè)用處践宴,是判斷值的類型。
( 重要 )
v instanceof Vehicle -------------- v是否是Vehicle的實(shí)例
// 等同于
Vehicle.prototype.isPrototypeOf(v) ----- Vehicle.prototype是否是v的原型
解析:
1. isPrototypeOf() 方法允許你檢查一個(gè)對(duì)象是否存在于另一個(gè)對(duì)象的原型鏈上
2. isPrototypeOf()返回的是布爾值
- instanceof的原理是檢查右邊構(gòu)造函數(shù)的prototype屬性爷怀,是否在左邊對(duì)象的原型鏈上阻肩。有一種特殊情況,就是左邊對(duì)象的原型鏈上运授,只有null對(duì)象烤惊。這時(shí),instanceof判斷會(huì)失真吁朦。
( 重要 )
var obj = Object.create(null);
typeof obj // "object"
Object.create(null) instanceof Object // false
解析:
1. Object.create()
該方法接受一個(gè)對(duì)象作為參數(shù)柒室,然后以它為原型,返回一個(gè)實(shí)例對(duì)象逗宜。
該實(shí)例完全繼承原型對(duì)象的屬性雄右。
即:object.create()方法 以參數(shù)對(duì)象為原型,生成實(shí)例對(duì)象
2. instanceof的原理是檢查右邊構(gòu)造函數(shù)的prototype對(duì)象是否在左邊對(duì)象的原型鏈上
3. Object.create(null) instanceof Object
因?yàn)橛疫?Object.prototype === null纺讲,不在左邊對(duì)象的原型鏈上
左邊對(duì)象的原型鏈在Object.prototype對(duì)象上終止
instanceof 用來判斷值得類型
但是注意:instanceof 運(yùn)算符只能用于對(duì)象擂仍,不適用原始類型的值。
此外刻诊,對(duì)于 undefined 和 null 防楷,instanceOf 運(yùn)算符總是返回 false。
var x = [1, 2, 3];
var y = {};
x instanceof Array // true
y instanceof Object // true
var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype // true
undefined instanceof Object // false
null instanceof Object // false
Object.getPrototypeOf()
Object.getPrototypeOf() 返回參數(shù)對(duì)象的原型则涯,是獲取原型對(duì)象的標(biāo)準(zhǔn)方法
( 重要 )
var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype // true
解析:
1. Object.getPrototypeOf() 返回參數(shù)對(duì)象的原型
2. f 的原型是 構(gòu)造函數(shù)F的 prototype屬性
幾種特殊對(duì)象的原型
1. 空對(duì)象的原型是 Object.prototype
2. Object.prototype 的原型是 null
3. 函數(shù)的原型是 Function.prototype
Object.setPrototypeOf() --- 注意 返回的是參數(shù)對(duì)象
Object.setPrototypeOf方法為參數(shù)對(duì)象設(shè)置原型复局,返回該參數(shù)對(duì)象。它接受兩個(gè)參數(shù)粟判,第一個(gè)是現(xiàn)有對(duì)象亿昏,第二個(gè)是原型對(duì)象。
- Object.setPrototypeOf() 返回該參數(shù)對(duì)象档礁。
- Object.setPrototypeOf() 接受兩個(gè)參數(shù)角钩,第一個(gè)是現(xiàn)有對(duì)象(
參數(shù)對(duì)象
),第二個(gè)是原型對(duì)象 - Object.setPrototypeOf() 為參數(shù)對(duì)象設(shè)置原型
( 重要 )
var a = {};
var b = {x: 1};
Object.setPrototypeOf(a, b); // {}
Object.getPrototypeOf(a) === b // true
a.x // 1
解析:
1. Object.setPrototypeOf(參數(shù)對(duì)象,原型對(duì)象) --- 返回的是參數(shù)對(duì)象
2. Object.setPrototypeOf()方法的作用是: 把第二個(gè)參數(shù)設(shè)置成第一個(gè)參數(shù)的原型
- new命令可以使用Object.setPrototypeOf方法模擬递礼。
( 重要 ) --- new命令的原理
var F = function () {
this.foo = 'bar';
};
var f = new F();
// 等同于
var f = Object.setPrototypeOf({}, F.prototype); --- 將空對(duì)象的原型設(shè)置成 F的prototype屬性
F.call(f); --------------------------------------- 將F中的this指向 空對(duì)象惨险,并執(zhí)行構(gòu)造函數(shù)
Object.create() --- 返回參數(shù)對(duì)象的實(shí)例對(duì)象
Object.create()接受一個(gè)對(duì)象作為參數(shù),然后以它為原型脊髓,返回一個(gè)實(shí)例對(duì)象辫愉。該實(shí)例完全繼承原型對(duì)象的屬性。
- Object.create() 以參數(shù)對(duì)象為原型将硝,返回實(shí)例對(duì)象恭朗。
// 原型對(duì)象
var A = {
print: function () {
console.log('hello');
}
};
// 實(shí)例對(duì)象
var B = Object.create(A);
Object.getPrototypeOf(B) === A // true
B.print() // hello
B.print === A.print // true
- 下面三種方式生成的新對(duì)象是等價(jià)的。
var obj1 = Object.create({});
var obj2 = Object.create(Object.prototype);
var obj3 = new Object();
- 如果想要生成一個(gè)不繼承任何屬性(比如沒有toString和valueOf方法)的對(duì)象依疼,可以將Object.create的參數(shù)設(shè)為null痰腮。
var obj = Object.create(null);
obj.valueOf()
// TypeError: Object [object Object] has no method 'valueOf
- 使用Object.create方法的時(shí)候,必須提供對(duì)象原型律罢,如果參數(shù)為空膀值,或者不是對(duì)象,都會(huì)報(bào)錯(cuò)弟翘。
Object.create()
// TypeError: Object prototype may only be an Object or null
Object.create(123)
// TypeError: Object prototype may only be an Object or null
- Object.create方法生成的新對(duì)象虫腋,動(dòng)態(tài)繼承了原型。在原型上添加或修改任何方法稀余,會(huì)立刻反映在新對(duì)象之上悦冀。
var obj1 = { p: 1 };
var obj2 = Object.create(obj1);
obj1.p = 2;
obj2.p // 2
Object.create方法生成的對(duì)象,繼承了它的原型對(duì)象的構(gòu)造函數(shù)睛琳。
( 重要 )
function A() {}
var a = new A();
var b = Object.create(a);
b.constructor === A // true
b instanceof A // true
解析:
1. Object.create()方法生成的對(duì)象盒蟆,繼承了它的原型對(duì)象的構(gòu)造函數(shù)
2. var b = Object.create(a); ---- b的原型是a, b繼承了a的構(gòu)造函數(shù)
所以 b.constructor === A // true
所以 b instanceof A // true
Object.prototype.isPrototypeOf() - 返回布爾值
isPrototypeOf方法被實(shí)例對(duì)象所繼承
實(shí)例對(duì)象的 isPrototypeOf() 方法,用來判斷該對(duì)象是否是參數(shù)對(duì)象的原型
- 只要實(shí)例對(duì)象處在參數(shù)對(duì)象的原型鏈上师骗, isPrototypeOf 方法就返回true
Object.prototype.__proto__
- 實(shí)例對(duì)象的
__proto__
返回該實(shí)例對(duì)象的原型 -
__proto__
該屬性可讀寫 - 只需要瀏覽器才需要部署該屬性历等,是一個(gè)內(nèi)部屬性
- 盡量少用
__proto__
屬性,而是使用
Object.getPrototypeOf()
讀參數(shù)對(duì)象的原型
Object.setPrototypeOf()
寫第一個(gè)參數(shù)對(duì)象的原型為第二個(gè)參數(shù)對(duì)象
componentDidMount() {
const obj1 = {};
const obj2 = {'name': 'wang'};
obj1.__proto__ = obj2;
console.log(obj2.isPrototypeOf(obj1), '實(shí)例對(duì)象的isPrototypeOf()放回一個(gè)布爾值辟癌,表示實(shí)例對(duì)象是否是參數(shù)對(duì)象的原型');
console.log(Object.getPrototypeOf(obj1), 'getPrototypeOf()方法寒屯,返回參數(shù)對(duì)象的原型對(duì)象');
}
獲取原型對(duì)象的方法比較
獲取實(shí)例對(duì)象的原型有三種方法: Object.getPrototypeOf()勝出
-
obj.__proto__
實(shí)例對(duì)象繼承的__proto__
屬性 -
obj.constructor.prototype
----- 實(shí)例的constructor是繼承自實(shí)例構(gòu)造函數(shù)的 prototype上的constructor Object.getPrototypeOf()
(重要) -- 比較三種獲取原型的方法
1. __proto__ 只在瀏覽器上有 ---- 不靠譜
2. obj.constructor.prototype在手動(dòng)修改原型時(shí),還要修改構(gòu)造函數(shù)黍少,否則可能會(huì)失效
結(jié)論:使用Object.getPrototypeOf() 最好
Object.prototype.hasOwnProperty
判斷某個(gè)屬性寡夹,是在對(duì)象自身屬性還是繼承屬性
- 實(shí)例對(duì)象的 hasOwnProperty 屬性返回一個(gè)布爾值,用于判斷某個(gè)屬性定義在對(duì)象自身厂置,還是定義在原型鏈上
- hasOwnProperty是js中唯一一個(gè)處理對(duì)象屬性時(shí)菩掏,不會(huì)遍歷原型鏈的方法
in運(yùn)算符
in運(yùn)算符返回一個(gè)布爾值,表示一個(gè)對(duì)象是否具有某個(gè)屬性
- 注意: ( in ) 運(yùn)算符 ( 不區(qū)分 ) 是 ( 自身屬性 ) 還是 ( 繼承屬性 )
for ...in 循環(huán)
自身屬性和繼承屬性都會(huì)被for...in循環(huán)遍歷
- 為了只遍歷自身屬性昵济,可以在for...in循環(huán)內(nèi)部智绸,用hasOwnProperty來過濾只有是自身屬性時(shí)野揪,才遍歷
const obj1 = {'name': 'wang'};
const obj2 = {'age': 20};
Object.setPrototypeOf(obj1, obj2);
for(let x in obj1) {
console.log(x, 'x')
}
// name x
// age x
for(let y in obj1) {
if( obj1.hasOwnProperty(y) ) { ---- 參數(shù)屬性是否是實(shí)例對(duì)象的自身屬性
console.log(y, 'y')
}
}
// name y
對(duì)象的拷貝
如何要拷貝對(duì)象,需要有兩點(diǎn)相同
- 拷貝后的對(duì)象瞧栗,要與原對(duì)象具有相同的 原型對(duì)象
- 考背后的對(duì)象斯稳,要與元對(duì)象具有相同的 實(shí)例屬性
2018-7-1
語句
js程序的執(zhí)行單位是 (行),一般情況下沼溜,每一行就是一個(gè)語句平挑。
- 語句是為了完成某種任務(wù)而進(jìn)行的操作
- 語句以分號(hào)結(jié)尾,一個(gè)分號(hào)就表示一個(gè)語句的結(jié)束
- 多個(gè)語句可以寫在一行內(nèi)
- 分號(hào)前面可以沒有任何內(nèi)容系草,js將其視為空語句
var a = 1 + 3 ; var b = 'abc';
解析:
1. 語句:語句以分號(hào)結(jié)尾;多個(gè)語句可以寫在一行內(nèi)唆涝。
2. 表達(dá)式:為了得到返回值的計(jì)算式
3. 凡是預(yù)期為值的地方找都,都可以使用表達(dá)式
4. 賦值語句,等號(hào)右邊預(yù)期為值廊酣,所以可以使用各種表達(dá)式
表達(dá)式
表達(dá)式: 是一個(gè)為了得到返回值的計(jì)算式
語句和表達(dá)式的區(qū)別
語句是為了完成某種任務(wù)而進(jìn)行的操作能耻,一般不需要返回值
表達(dá)式是為了得到返回值,一定會(huì)返回一個(gè)值
js中亡驰,凡是預(yù)期為值的地方晓猛,都可以使用表達(dá)式(
重要
)
變量
變量是對(duì)值的具名引用
-
變量
是對(duì)值的具名引用
- 變量就是為值取名 ,引用這個(gè)名字凡辱,就是引用這個(gè)值 ----------------------------- ( 重要 )
- 變量的名字戒职,就是變量名
- 變量名區(qū)分大小寫
- 如果只是聲明變量裸燎,而未賦值揍堕,則改變量的值是 undefined
- 可以在同一條var命令中聲明多個(gè)變量
- JavaScript 是一種動(dòng)態(tài)類型語言涛癌,也就是說弛秋,變量的類型沒有限制古毛,變量可以隨時(shí)更改類型
函數(shù)
js把函數(shù)看成一種值牺六,凡是能使用值的地方丝蹭,就能使用函數(shù)
- 當(dāng)有return語句時(shí)秤掌,返回return后面緊跟的表達(dá)式
- 沒有return語句時(shí)汉操,返回undefined
- 函數(shù)只是一個(gè)可執(zhí)行的值
- (表達(dá)式是為了得到返回值的計(jì)算式再来,目的是為了得到返回值,預(yù)期為值的地方磷瘤,都可以使用表達(dá)式)
- 函數(shù)與其他數(shù)據(jù)類型地位相等芒篷,叫做第一等公民
函數(shù)名的提升
js將函數(shù)名,視同變量名膀斋。
- 在用function命令聲明函數(shù)時(shí)梭伐,function后面的變量名存在變量提升
- 注意:采用變量賦值時(shí),如果先調(diào)用就會(huì)報(bào)錯(cuò)
- 因此仰担,如果同時(shí)采用function命令和賦值語句聲明同一個(gè)函數(shù)糊识,最后總是采用賦值語句的定義绩社。
- 不能在條件語句中聲明函數(shù) ( if ) 和 ( try )
( 重要 )
總結(jié):
用變量賦值的方法聲明函數(shù),和function聲明都存在變量提升
但是:變量賦值先調(diào)用會(huì)報(bào)錯(cuò)赂苗,而function聲明不會(huì)報(bào)錯(cuò)
( 先調(diào)用函數(shù)愉耙,function聲明不報(bào)錯(cuò),變量賦值聲明報(bào)錯(cuò) )
1. function命令聲明時(shí)的 ( 函數(shù)名提升 )
f();
function f() {}
不會(huì)報(bào)錯(cuò)
2. 變量賦值聲明函數(shù)
f();
var f = function (){};
報(bào)錯(cuò)TypeError: undefined is not a function拌滋,---------------- 實(shí)際上相當(dāng)于下面的代碼:
var f;
f();
f = function () {};
函數(shù)的name屬性
返回函數(shù)的名字
- function聲明的函數(shù)朴沿,返回function后面的函數(shù)名
- 變量賦值,匿名函數(shù)败砂,返回變量名
- 變量賦值赌渣,具名函數(shù),返回function后面的函數(shù)名
- name屬性的用處昌犹,就是獲得參數(shù)函數(shù)的名字
var myFunc = function () {};
function test(f) {
console.log(f.name);
}
test(myFunc) ----------------------- 返回 myFunc
上面代碼中坚芜,函數(shù)test內(nèi)部通過name屬性,就可以知道傳入的參數(shù)是什么函數(shù)斜姥。
length屬性
函數(shù)的length返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)
- 返回 ( 定義時(shí) ) 的 ( 參數(shù)個(gè)數(shù) )
- length方法提供了一種機(jī)制鸿竖,判斷定義時(shí)和調(diào)用時(shí)參數(shù)的差異,以便實(shí)現(xiàn)面向?qū)ο缶幊痰?br> ( 方法重載 ) overload
const a = function(a,b,c) {
return `${a},$铸敏,${c}`
};
console.log( a.length ); ------------------------- length返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù): 3
console.log( a(1,2) ); // 1,2,undefined
函數(shù)的toString方法
- toString方法返回一個(gè)字符串缚忧,內(nèi)容時(shí)函數(shù)的源碼 ( 包括函數(shù)內(nèi)部的注釋代碼 )
總結(jié): name屬性,length屬性,toString()方法
const a = function(a,b,c) {
return `${a},$杈笔,${c}`
};
console.log( a.toString(), 'toString方法闪水,返回函數(shù)的源碼字符串' )
console.log( a.length, 'length屬性,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)' );
console.log( a.name, 'name屬性返回函數(shù)的名字桩撮,function命令聲明敦第,時(shí)后面的函數(shù)名,變量賦值店量,匿名時(shí)變量名芜果,具名時(shí)function后的函數(shù)名')
console.log( a(1,2) );
結(jié)果:
function a(_a, b, c) {
return _a + ',' + b + ',' + c;
} toString方法,返回函數(shù)的源碼字符串
3 "length屬性融师,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)"
a name屬性返回函數(shù)的名字右钾,function命令聲明,時(shí)后面的函數(shù)名旱爆,變量賦值舀射,匿名時(shí)變量名,具名時(shí)function后的函數(shù)名
1,2,undefined
函數(shù)的作用域
( 作用域 ) scope指的是 ( 變量存在的范圍 )
es5有兩種作用域:( 全局作用域 ) 和 ( 函數(shù)作用域 )
es6新增一個(gè)作用域:( 塊級(jí)作用域 )
- 全局作用域:在整個(gè)程序中存在怀伦,任何地方都可以讀取
- 函數(shù)作用域:只能在函數(shù)內(nèi)部讀取脆烟,函數(shù)外部無法讀取。( 用回調(diào)函數(shù)解決 )
- 塊級(jí)作用域: 只在代碼塊內(nèi)有效
- 函數(shù)外部聲明的變量房待,是全局變量邢羔,可以在函數(shù)內(nèi)部讀取 (global variable全局變量)
- 函數(shù)內(nèi)部定義的變量驼抹,函數(shù)外部無法讀取,稱為局部變量 (local variable局部便變量)
- 函數(shù)內(nèi)部定義的變量拜鹤,會(huì)在該作用域內(nèi)框冀,覆蓋同名全局變量
注意: 對(duì)于var命令,局部變量只能在函數(shù)內(nèi)部聲明敏簿,在其他區(qū)塊聲明明也,一律都是全局變量
var a = 1;
var c = 3;
function x() {
console.log(a, '函數(shù)內(nèi)部,可以讀取函數(shù)外部的全局變量');
var b = 2;
var c = 4;
console.log(c, '函數(shù)內(nèi)部定義的變量惯裕,會(huì)在該作用域內(nèi)覆蓋同名全局變量')
}
x();
if(true) {
var y = 100;
}
console.log(y, '對(duì)于var命令來說温数,局部變量只能在函數(shù)中聲明,在其他區(qū)塊中聲明的變量都是全局變量')
console.log(b, '函數(shù)外部無法讀取函數(shù)內(nèi)部的變量')
函數(shù)內(nèi)部的變量提升
- 和全局作用域一樣轻猖,函數(shù)作用域也會(huì)產(chǎn)生變量提升現(xiàn)象
- var聲明的變量帆吻,不管在什么位置,變量聲明都會(huì)被提到函數(shù)頭部
function foo(x) {
if (x > 100) {
var tmp = x - 100;
}
}
-- 等同于
function foo(x) {
var tmp;
if (x > 100) {
tmp = x - 100;
};
}
函數(shù)本身的作用域
函數(shù)本身也是一個(gè)值咙边,也有自己的作用域
- 函數(shù)就是一個(gè)計(jì)算的值,凡是使用值的地方都可以使用函數(shù)
- 表達(dá)式就是為了得到返回值的計(jì)算式次员,目的是為了得到返回值败许,凡是預(yù)期為值的地方,都可以使用表達(dá)式
- 函數(shù)的作用域淑蔚,是其聲明時(shí)所在的作用域市殷,與其運(yùn)行時(shí)的作用域無關(guān)
函數(shù)的作用域,是函數(shù)聲明時(shí)的作用域刹衫,與函數(shù)運(yùn)行時(shí)的作用域無關(guān)
- 函數(shù)運(yùn)行時(shí)的作用域醋寝,是函數(shù)聲明時(shí)的作用域,與函數(shù)調(diào)用時(shí)的作用域無關(guān)
-
容易犯錯(cuò)的點(diǎn): 如果a函數(shù)調(diào)用b函數(shù)带迟,卻沒有考慮到b函數(shù)不會(huì)引用a函數(shù)內(nèi)部的變量
--------- ( 重要 )
var a = 1;
function x() {
console.log(a, '函數(shù)的作用域音羞,是函數(shù)聲明時(shí)的作用域,與函數(shù)調(diào)用時(shí)的作用域無關(guān)');
console.log('容易犯錯(cuò)的點(diǎn): 如果a函數(shù)調(diào)用b函數(shù)仓犬,卻沒有考慮到b函數(shù)不會(huì)引用a函數(shù)的變量');
}
function y() {
var a = 100;
x();
}
y(); ---------------- 結(jié)果是1
總結(jié):
- 函數(shù)外部聲明的函數(shù)嗅绰,作用域綁定在函數(shù)外部
- 函數(shù)內(nèi)部聲明的函數(shù),作用域綁定在函數(shù)內(nèi)部
( 重要 )
總結(jié):
1. 函數(shù)外部聲明的函數(shù)搀继,作用域綁定在函數(shù)外部
2. 函數(shù)內(nèi)部聲明的函數(shù)窘面,作用域綁定在函數(shù)內(nèi)部
第一個(gè)和第二點(diǎn)都滿足第三點(diǎn)
3. 函數(shù)的作用域,是函數(shù)聲明時(shí)的作用域叽躯,與函數(shù)調(diào)用時(shí)的作用域無關(guān) !!!!!!!!
(1)
var a = 1;
var x = function () {
console.log(a);
};
function y(f) {
var a = 2;
f();
}
y(x) -------- 結(jié)果是1 ( 函數(shù)的作用域财边,是函數(shù)聲明時(shí)的作用域,與函數(shù)調(diào)用時(shí)的作用域無關(guān) )
(2)
function foo() {
var x = 1;
function bar() {
console.log(x);
}
return bar;
}
var x = 2;
var f = foo();
f() -------- 結(jié)果是1 ( 函數(shù)的作用域点骑,是函數(shù)聲明時(shí)的作用域酣难,與函數(shù)調(diào)用時(shí)的作用域無關(guān) )
參數(shù)
- 函數(shù)沒辦法省略靠前的參數(shù)谍夭,而保留靠后的參數(shù)
- 如果一點(diǎn)要省略靠前的參數(shù),只有顯示的傳入 undefined
function f(a, b) {
return a;
}
f( , 1) // SyntaxError: Unexpected token ,(…) 省略前面報(bào)錯(cuò)
f(undefined, 1) // undefined 一定要省略前面鲸鹦,則只要傳入undefined
參數(shù)的傳遞方式
- 函數(shù)的參數(shù)如果是原始類型的值(數(shù)值慧库,字符串,布爾值)馋嗜,傳遞方法是( 傳值傳遞 )齐板,
傳遞的是原始值的拷貝,在函數(shù)體內(nèi)修改參數(shù)葛菇,不會(huì)影響到函數(shù)外部
- 函數(shù)的參數(shù)如果是原始類型的值(數(shù)值慧库,字符串,布爾值)馋嗜,傳遞方法是( 傳值傳遞 )齐板,
- 函數(shù)的參數(shù)是復(fù)合類型的值(數(shù)組甘磨,對(duì)象,其他函數(shù))眯停,傳遞方式是( 傳址傳遞 )济舆,
傳遞的是原始值的地址指針,在函數(shù)內(nèi)部修改參數(shù)莺债,會(huì)影響到原始值
- 函數(shù)的參數(shù)是復(fù)合類型的值(數(shù)組甘磨,對(duì)象,其他函數(shù))眯停,傳遞方式是( 傳址傳遞 )济舆,
- 注意:如果函數(shù)內(nèi)部修改的不是參數(shù)對(duì)象的某個(gè)屬性滋觉,而是替換掉整個(gè)參數(shù),這時(shí)不會(huì)影響到原始值
- reference是引用的意思
- ( 變量 ) 分為 ( 基本類型 ) 和 ( 引用類型 )
let str = 'abcdef';
let num = 12345;
let boo = true; ------------------------------------ 原始類型的值
let arr = [1,2,3,4,5];
let obj = {'name': 'wang'}; ------------------------- 復(fù)合類型的值
let replaceArr = [1,2];
let replaceObj = {'name': 'zhang'} ------------------ 復(fù)合類型的值
function pass(num,str,boo, arr,obj,fun, replaceArr,replaceObj) {
num = 100;
str = 'oneHundred';
boo = false; ---------- 參數(shù)是原始類型的值齐邦,傳值傳遞椎侠,修改參數(shù),不影響原始值
arr[0] = 100;
obj.name = 'li'; --------- 參數(shù)是復(fù)合類型的值措拇,傳址傳遞我纪,修改參數(shù),影響原始值
replaceArr = [1,1,1];
replaceObj = {'age': 30} --- 替換掉整個(gè)復(fù)合類型的參數(shù)丐吓,不會(huì)影響到原始值
}
pass(str, num, boo, arr, obj, replaceArr, replaceObj);
console.log(str, num, boo);
console.log(arr, obj);
console.log(replaceArr, replaceObj);
結(jié)果:
abcdef 12345 true
[100, 2, 3, 4, 5] {name: "li"}
[1, 2] {name: "zhang"}
同名參數(shù)
如果有同名參數(shù)浅悉,則取最后出現(xiàn)的那個(gè)值
function f(a, a) {
console.log(a);
}
f(1, 2) // 2
-------------------------------------
function f(a, a) {
console.log(a);
}
f(1) // undefined
arguments對(duì)象
arguments對(duì)象包含了函數(shù) ( 運(yùn)行時(shí)的所有參數(shù) )
- arguments[0] 是第一個(gè)參數(shù),arguments[1] 是第二個(gè)參數(shù)券犁,以此類推...
- arguments對(duì)象只能在函數(shù)內(nèi)部使用
正常模式下术健,arguments對(duì)象可以在運(yùn)行時(shí)修改
嚴(yán)格模式下,arguments對(duì)象是一個(gè)只讀對(duì)象族操,修改無效苛坚,當(dāng)不會(huì)報(bào)錯(cuò)
- arguments對(duì)象有一個(gè)callees屬性,返回它對(duì)應(yīng)的原函數(shù)
function a(b,c,d,e) {
console.log(arguments.length, 'arguments.length返回調(diào)用時(shí)傳入的參數(shù)個(gè)數(shù)色难,是調(diào)用時(shí)的參數(shù)個(gè)數(shù)');
arguments[0] = 100;
console.log(arguments[0], 'arguments對(duì)象泼舱,可以在運(yùn)行時(shí)修改');
console.log('在嚴(yán)格模式下,arguments對(duì)象是只讀枷莉,修改無效娇昙,當(dāng)不會(huì)報(bào)錯(cuò)');
}
a(1,2,3);
console.log(a.length, '函數(shù)的length屬性,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)');
console.log( arguments[1] ,'arguments對(duì)象只能在函數(shù)內(nèi)部使用')
console.log(arguments.callee, 'arguments對(duì)象的callee屬性笤妙,返回它對(duì)應(yīng)的原函數(shù)');
結(jié)果:
3 "arguments.length返回調(diào)用時(shí)傳入的參數(shù)個(gè)數(shù)冒掌,是調(diào)用時(shí)的參數(shù)個(gè)數(shù)"
100 "arguments對(duì)象噪裕,可以在運(yùn)行時(shí)修改"
在嚴(yán)格模式下,arguments對(duì)象是只讀股毫,修改無效膳音,當(dāng)不會(huì)報(bào)錯(cuò)
4 "函數(shù)的length屬性,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)"
undefined "arguments對(duì)象只能在函數(shù)內(nèi)部使用"
報(bào)錯(cuò): callee不能用于嚴(yán)格模式铃诬,react的類默認(rèn)就是嚴(yán)格模式
注意:
1. 函數(shù)的length屬性祭陷,返回函數(shù)定義時(shí)的參數(shù)個(gè)數(shù)
2. arguments.length屬性,返回函數(shù)調(diào)用時(shí)傳入的參數(shù)個(gè)數(shù)
3. arguments對(duì)象只能在函數(shù)內(nèi)部使用
閉包
閉包是定義在函數(shù)內(nèi)部的函數(shù)
- 函數(shù)的作用域是函數(shù)定義時(shí)的作用域趣席,與調(diào)用時(shí)的作用域無關(guān)
- 閉包的用處:
- 讀取函數(shù)內(nèi)部的變量
- 將這些變量保存在內(nèi)存中兵志,即閉包可以記住它的誕生環(huán)境一直存在
- 封裝對(duì)象的私有屬性和私有方法
( 重要 )
function f1() {
var n = 999;
function f2() {
console.log(n);
}
return f2;
}
var n = 111;
var result = f1();
result(); // 999
解析:
1. 函數(shù)的作用域,是函數(shù)定義時(shí)的作用域宣肚,與函數(shù)調(diào)用時(shí)的作用域無關(guān)
2. f2聲明在f1的內(nèi)部想罕,f2調(diào)用時(shí),f2的作用域是定義時(shí)候的作用域霉涨,即在f1的內(nèi)部按价,所以是999,不是111
3. 閉包就是定義在一個(gè)函數(shù)內(nèi)部的函數(shù)笙瑟,注意: 一定是要在函數(shù)內(nèi)部定義 7恪!逮走!
( 閉包 )
function createIncrementor(start) {
return function () {
return start++;
};
}
var inc = createIncrementor(5);
inc() // 5
inc() // 6
inc() // 7
解析:
1. 閉包inc使得函數(shù)createIncrementor的內(nèi)部環(huán)境,一直存在今阳。
2. inc始終在內(nèi)存中师溅,而inc的存在依賴于createIncrementor,因此也始終在內(nèi)存中
不會(huì)在調(diào)用結(jié)束后盾舌,被垃圾回收機(jī)制回收墓臭。
- 閉包用于封裝對(duì)象的私有屬性和私有方法
閉包:用與封裝對(duì)象的私有屬性和私有方法
function Person(name) {
var _age;
function setAge(n) {
_age = n;
}
function getAge() {
return _age;
}
return {
name: name,
getAge: getAge,
setAge: setAge
};
}
var p1 = Person('張三');外層函數(shù)每次運(yùn)行,都會(huì)生成一個(gè)新的閉包妖谴,閉包保存外層函數(shù)的內(nèi)部變量窿锉,內(nèi)存消耗大
p1.setAge(25);
p1.getAge() // 25
注意:
1. 外層函數(shù)每次運(yùn)行,都會(huì)生成一個(gè)新的閉包膝舅,而這個(gè)閉包又會(huì)保留外層函數(shù)的內(nèi)部變量嗡载,所以內(nèi)存消耗很大。
2. 因此不能濫用閉包仍稀,否則會(huì)造成網(wǎng)頁的性能問題洼滚。
立即調(diào)用函數(shù)表達(dá)式
有時(shí)候,我們需要在定義函數(shù)之后技潘,立即調(diào)用該函數(shù)遥巴。這時(shí)千康,你不能在函數(shù)的定義之后加上圓括號(hào),這會(huì)產(chǎn)生語法錯(cuò)誤铲掐。
- 產(chǎn)生錯(cuò)誤的原因是function關(guān)鍵字拾弃,可以作為語句,也可以作為表達(dá)式
-
語句
:用分號(hào)結(jié)尾摆霉,多個(gè)語句可以在一行豪椿。 -
表達(dá)式
:為了得到返回值的計(jì)算式,凡是預(yù)期為值的地方都可以使用表達(dá)式斯入; -
js規(guī)定砂碉,function關(guān)鍵字在行首,一律解釋成語句刻两。
因此增蹭,JavaScript引擎看到行首是function關(guān)鍵字之后,認(rèn)為這一段都是函數(shù)的定義磅摹,不應(yīng)該以圓括號(hào)結(jié)尾滋迈,所以就報(bào)錯(cuò)了。 - 解決方法就是不要讓function出現(xiàn)在行首户誓,讓引擎將其理解成一個(gè)表達(dá)式饼灿。最簡(jiǎn)單的處理,就是將其放在一個(gè)圓括號(hào)里面帝美。
- 總結(jié):
- function出現(xiàn)在行首碍彭,是語句。語句不能以括號(hào)
()
結(jié)尾悼潭,必須以分號(hào);
結(jié)尾
- function出現(xiàn)在行首碍彭,是語句。語句不能以括號(hào)
- 用變量賦值方法聲明的函數(shù)庇忌,function...是一個(gè)表達(dá)式,直接加
()
就能立即執(zhí)行調(diào)用
- 用變量賦值方法聲明的函數(shù)庇忌,function...是一個(gè)表達(dá)式,直接加
- 如果function在行首舰褪,又要立即調(diào)用皆疹,包一層括號(hào)即可
( 重要 )
語句
function f() {} ------- 函數(shù)的聲明語句
表達(dá)式
var f = function f() {} -------- 等號(hào)右邊預(yù)期是值,function是表達(dá)式占拍,函數(shù)就是一個(gè)可執(zhí)行的值
(function(){ ... }()); ------------- 語句不能以括號(hào)結(jié)尾略就,而是以分號(hào)結(jié)尾
// 或者
(function(){ ... })();
注意,上面兩種寫法最后的分號(hào)都是必須的晃酒。
如果省略分號(hào)表牢,遇到連著兩個(gè) IIFE,可能就會(huì)報(bào)錯(cuò)掖疮。
--------------------------
注意: 如果是采用變量賦值的方式聲明函數(shù)初茶,那么function本來就是表達(dá)式,所以可以直接加括號(hào)
const a = function() {
console.log('11111111')
}();
eval命令
eval命令的作用是,將字符串當(dāng)作語句執(zhí)行
- eval命令的作用是將字符串恼布,當(dāng)作語句執(zhí)行
eval('var a = 1;');
a // 1