Pull to refresh

Отличие Javascript от PHP o_0

Reading time 4 min
Views 5.9K
Доброго времени суток уважаемый %username%
Вот появился на хабре такой замечательный топик Отличие Javascript от PHP ;) не читал, но осуждаю Не знаю чем там всё закончилось все комментарии не смог перечитать, но хотелось бы развеять пару заблуждений и неточностей которые были допущены автором

итак начнём
«По умолчанию, всё передается по значению, и объекты тоже
В PHP попытались возвести в абсолют концепцию языка С, что всё передается по значению. И они поначалу сделали это даже для объектов, но потом немного поменяли концепцию — объекты по-прежнему являются значениями, но это значение представляет из себя ссылку на инстанс класса.» — ложь, в PHP объекты передаются только по ссылке. Objects and references (%username% нужно ли разложить по полочкам почему это так — нужен ли отдельный топик посвященный способу передачи объектов. Я не хочу делать дурацкий топик-вопрос, по этому первый комментарий к этому посту будет вопросом «нужен ли отдельный топик посвященный способу передачи объектов» если да то плюсуем, если нет ставим минус)
дальше пример автора
PHP:
<?php
$arr = array(
'key1' => 'value1',
'key2' => 'value2',
);

function doSmthWithArray($arr) {
$arr['key3'] = 'value3';
}

doSmthWithArray($arr);
print_r($arr); // выведет "key1 => value1, key2 => value2" — исходный массив не изменился


Javascript:
var arr = {
key1: 'value1',
key2: 'value2'
};

function doSmthWithArray(arr) {
arr['key3'] = 'value3';
}

doSmthWithArray(arr);
console.log(arr); // выведет "key1 => value1, key2 => value2, key3 => value3" — т.к. в JS, по сути, нет встроенного типа «хеш», то это объект, и он передался по ссылке (впрочем, семантика передачи объектов — это отдельная тема. Конечно, просто сама по себе переменная представляет из себя ссылку на инстанс объекта, а не передача идет по ссылке, но это уже детали) 

Итак пример более чем некорректен. Почему? Ну во первых в JavaScript почти всё является object -ми

«JavaScript is almost entirely object-based. JavaScript objects are associative arrays, augmented with prototypes (see below). Object property names are string keys: obj.x = 10 and obj['x'] = 10 are equivalent, the dot notation being syntactic sugar. Properties and their values can be added, changed, or deleted at run-time. Most properties of an object (and those on its prototype inheritance chain) can be enumerated using a for...in loop. JavaScript has a small number of built-in objects such as Function and Date.» говорит нам Википедия
Значит var arr полноценный объект передающийся по ссылке.

В нашем любимом PHP тип array не является объектом. (Сколько всего типов в PHP? Ответ тут) а как мы с вами знаем только object передаётся по ссылке, всё остальное по значению. Вот почему в примере автора исходный массив остаётся неизменным. Можно ли привести массив к объекту? Да
<?php
$arr = array(
'key1' => 'value1',
'key2' => 'value2',
);
$ArrayObject = (object) $arr;
var_dump($ArrayObject);
$anotherArrayObject = new ArrayObject($arr);
var_dump($anotherArrayObject);


Либо явно преобразовываем к типу object либо используем встроенный класс ArrayObject в первом случае $ArrayObject становится объектом свойства которого это ключи исходного массива, а значения этих свойств — значения массива. Во втором случае наш массив стал объектом типа ArrayObject ознакомиться с которым вы можете по приведенной выше ссылке. А теперь когда наш массив стал объектом давайте-ка запустим пример автора оригинальной статьи с модификациями
$arr = array(
'key1' => 'value1',
'key2' => 'value2',
);
$arr = new ArrayObject($arr);

function doSmthWithArray($arr) {
$arr['key3'] = 'value3';
}

doSmthWithArray($arr);
print_r($arr);

echo $arr['key3'];

А теперь запустите этот код и посмотрите на результат! Ну что передаются объекты в PHP по ссылке?
ArrayObject Object
(
    [storage:ArrayObject:private] => Array
        (
            [key1] => value1
            [key2] => value2
            [key3] => value3
        )

)
value3

Дальше у автора оригинальной статьи идет вот это:
«Copy-on-write

Вот об этом точно далеко не все знают. Если вкратце: хоть в PHP и всё передается по значению, но, на самом деле, копирование происходит далеко не всегда. Оно происходит, когда значение изменяется внутри конструкции, как, например, было в первом примере. Но это не единственный случай, когда создается копия. Подробнее об этом по ссылке.» Я не очень понял о чем это. Мы с вами уже выяснили, что простые типы передаются по значению объекты по ссылке.

Всем дочитавшим до этого места огромное спасибо. Надеюсь я немного разъяснил путаницу с передачей объектов по ссылкам. Да не забываем про мини голосование. За любые неточности, ошибки, неприятное оформление прощу прощение заранее да и за то если этот топик нафиг никому не нужен :)

UPD1: Господа это топик ответ на Отличие Javascript от PHP ;)
UPD2: Минусующие с чем именно вы не согласны? В том что в PHP объект таки передаётся по ссылке?
UPD3: Может я не правильно выразился но
Передача параметра по значению

Передача параметра по значению означает что вызывающая функция копирует в память, доступную вызываемой, (обычно стек) непосредственное значение. Изменение копии переменной, соответственно, оригинал не затрагивает.

Передача параметра по ссылке
Передача параметра по ссылке означает что копируется не само значение, а адрес исходной переменной.
Передача по ссылке позволяет избежать копирования всей информации, описывающей состояние объекта. Изменение состояния параметра переданного по ссылке влечёт за собой изменения оригинального объекта.

Таким образом, всё что я хотел сказать, что объекты и так передаются по ссылке, ( да на самом деле получается передача по значению адрес в памяти, по которому можно найти оригинальный объект ) Но давайте всё сведём к следующему простой тип передаётся по значению (Изменение копии переменной, соответственно, оригинал не затрагивает.)
, объект по ссылке (Изменение состояния параметра переданного по ссылке влечёт за собой изменения оригинального объекта.)
$test = 'LOREM IPSUM';
function byValue($param) {
	$param = strtolower($param);
}
byValue($test);
echo $test.PHP_EOL;

$object = new stdClass();
function byReference($param){
	$param->foo = 'bar';
}
byReference($object);
var_dump($object);


Мне в личку сыпятся вопросы, я на всё отвечу, просто сейчас не могу так как работаю. Отвечу как освобожусь спасибо.
Tags:
Hubs:
+23
Comments 75
Comments Comments 75

Articles