Javascript 1 - function, object, prototype
Function definition
//函数声明式定义
function foo(num1,num2){
return num1 + num2;
}
//函数表达式定义
var foo = function(num1,num2){
return num1 + num2;
};
//使用Function构造函数定义
var foo = new Function("num1","num2","return num1 + num2");
//实际上创建一个Function实例并不一定要赋值给具体的指针,可以直接执行
(function(x,y){return x+y})(1,2);
//之所以用圆括号把function(){}括起来是因为js解释器会将function解释为函数声明,而函数声明不能直接跟着(x,y),我们需要将其转换为函数表达式。
//(1,2)表示要传递跟函数的参数。
IIFE
An IIFE (Immediately Invoked Function Expression) is a JavaScript function that runs as soon as it is defined. (function () { statements })();.
In jQuery, the fn property is just an alias to the prototype property. jQuery identifier (or $) is just a constructor function.
function Test() {
this.a = 'a';
}
Test.prototype.b = 'b';
var test = new Test();
test.a; // "a", own property
test.b; // "b", inherited property
(function() {
var foo = function(arg) { // core constructor
// ensure to use the `new` operator
if (!(this instanceof foo))
return new foo(arg);
// store an argument for this example
this.myArg = arg;
//..
};
// create `fn` alias to `prototype` property
foo.fn = foo.prototype = {
init: function () {/*...*/}
//...
};
// expose the library
window.foo = foo;
})();
// Extension:
foo.fn.myPlugin = function () {
alert(this.myArg);
return this; // return `this` for chainability
};
foo("bar").myPlugin(); // alerts "bar"
Before ES6, to avoid global method name conflicts, add method to a object. After ES6, use commonJS.
// bad
let find = () => {};
let remove = () => {};
// good
$.fn.find = () => {};
$.fn.remove = () => {};
// good
(function($) {
let find = () => {};
let remove = () => {};
$.fn.find = find;
$.fn.remove = remove;
}(jQuery))
函数作为构造函数进行调用,this指向new出的那个对象
color = 'red';
var o = {color: 'blue'};
function sayColor() {
console.log(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(o); //blue
<script>
var x = 0;
function test(){
this.x = 1;
}
var obj = new test();
console.log(obj.x); //1(说明this指向obj)
</script>
JavaScript has no overload
var sum(){
return arguments[0] + arguments[1]; //通过arguments对象执行内部操作
}
console.log(sum(1, 2)); //3
function add(num1, num2){
return num1 + num2;
}
function add(value){
return value + 100;
}
console.log(add(1, 2)); //101
instance.proto === constructor.prototype
var 对象 = new 函数()
对象.__proto__ === 对象的构造函数.prototype
constructor1.prototype = instance2
鉴于上述游戏规则生效,如果试图引用constructor1构造的实例instance1的某个属性p1:
1).首先会在instance1内部属性中找一遍;
2).接着会在instance1.proto(constructor1.prototype)中找一遍,而constructor1.prototype 实际上是instance2, 也就是说在instance2中寻找该属性p1;
3).如果instance2中还是没有,此时程序不会灰心,它会继续在instance2.proto(constructor2.prototype)中寻找...直至Object的原型对象
搜索轨迹: instance1--> instance2 --> constructor2.prototype…-->Object.prototype
function Father(){
this.property = true;
}
Father.prototype.getFatherValue = function(){
return this.property;
}
function Son(){
this.sonProperty = false;
}
//继承 Father
Son.prototype = new Father();//Son.prototype被重写,导致Son.prototype.constructor也一同被重写
Son.prototype.getSonVaule = function(){
return this.sonProperty;
}
var instance = new Son();
alert(instance.getFatherValue());//true
alert(instance instanceof Object);//true
alert(instance instanceof Father);//true
alert(instance instanceof Son);//true
alert(Object.prototype.isPrototypeOf(instance));//true
alert(Father.prototype.isPrototypeOf(instance));//true
alert(Son.prototype.isPrototypeOf(instance));//true
New
第一行,我们创建了一个空对象obj;
第二行,我们将这个空对象的__proto__成员指向了F函数对象prototype成员对象;
第三行,我们将F函数对象的this指针替换成obj,然后再调用F函数.
var obj = {};
obj.__proto__ = F.prototype;
F.call(obj);
Another way:
subClass.prototype = superClass.prototype;//直接指向超类型prototype
function Person() {
}
var person = new Person();
console.log(person.__proto__ == Person.prototype) // true
console.log(Person.prototype.constructor == Person) // true
// 顺便学习一个ES5的方法,可以获得对象的原型
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
console.log(person.constructor === Person); // true
当获取 person.constructor 时,其实 person 中并没有 constructor 属性,当不能读取到constructor 属性时,会从 person 的原型也就是 Person.prototype 中读取,正好原型中有该属性,所以:person.constructor === Person.prototype.constructor
function vs object
function is a object with prototype
var o1 = {};
var o2 =new Object();
var o3 = new f1();
function f1(){};
var f2 = function(){};
var f3 = new Function('str','console.log(str)');
console.log(typeof Object); //function
console.log(typeof Function); //function
console.log(typeof f1); //function
console.log(typeof f2); //function
console.log(typeof f3); //function
console.log(typeof o1); //object
console.log(typeof o2); //object
console.log(typeof o3); //object
prototype
function Person() {}
Person.prototype = {
name: 'Zaxlct',
age: 28,
job: 'Software Engineer',
sayName: function() {
console.log(this.name);
}
}
var person1 = new Person();
person1.sayName(); // 'Zaxlct'
var person2 = new Person();
person2.sayName(); // 'Zaxlct'
console.log(person1.sayName == person2.sayName); //true
问:为什么 [1, 2, 3].map(parseInt) 返回 [1,NaN,NaN]?
答:parseInt 函数的第二个参数表示要解析的数字的基数。该值介于 2 ~ 36 之间。map will pass both value and index.
... for shallow copy
var a = { name: 'ygy', age: 20 };
var b = { ...a };
use && to replace if
// old
if (callback) callback();
// new
callback && callback();
// use && to get value
var obj = {
info: {
name: 'ygy'
}
}
obj.info && obj.info.name; // 'ygy'
|| to get default value
var b = a || 10; // 如果a是空值,那么b就是10
This
var a = 1;
var obj1 = {
a:2,
fn:function(){
console.log(this.a);
}
}
var fn1 = obj1.fn;
var fn1bind = fn1.bind(obj1);
fn1();//1 //window
obj1.fn();//2 //object
fn1bind();//2
fn1.call(obj1);//2
fn1.apply(obj1);//2
document.addEventListener('click', function(e){
console.log(this); //document
setTimeout(function(){
console.log(this); //window
}, 200);
}, false);
//constructor的this都指向实例
function Person(name,age){
this.name = name;
this.age = age;
this.sayAge = function(){
console.log(this.age);
}
}
var dot = new Person('Dot',2);
dot.sayAge();//2
Use closure to make variable private
// 闭包版
const Student = function(age, sex) {
let _age = age, _sex = sex;
const setAge = (newAge) => {
_age = 20;
}
const getAge = () => {
return _age;
}
return {
setAge,
getAge
}
}
const student = new Student(20, 'female');
console.log(student._age); // undefined